ใช้ CASE เพื่อเลือกคอลัมน์ในแบบสอบถามแบบ UPDATE หรือไม่


13

ฉันสามารถใช้CASEเพื่อเลือกคอลัมน์ที่จะแสดงในSELECTแบบสอบถาม (Postgres) เช่น:

SELECT CASE WHEN val = 0 THEN column_x
            WHEN val = 1 THEN column_y
            ELSE 0
       END AS update, ...

มีความคล้ายคลึงกันหรือไม่เมื่อดำเนินการUPDATEค้นหาใน Postgres (เช่นเลือกคอลัมน์ที่ควรได้รับการอัปเดต)? ฉันคิดว่าไม่ใช่เพราะฉันไม่พบอะไรเกี่ยวกับเรื่องนี้ แต่อาจมีบางคนมีทางเลือกที่ฉลาด (นอกเหนือจากการใช้โพรซีเดอร์หรืออัปเดตแต่ละคอลัมน์โดยใช้ a CASEเพื่อพิจารณาว่าควรกำหนดค่าของคอลัมน์ใหม่หรือมอบหมายค่าเดิม ราคา). หากไม่มีทางเลือกอื่นที่ง่ายแน่นอนฉันจะยอมรับว่าเป็นคำตอบเช่นกัน

ข้อมูลเพิ่มเติม : ในกรณีของฉันฉันมีคอลัมน์ที่อาจเกิดขึ้น 14 คอลัมน์ซึ่งอาจได้รับการอัปเดตโดยมีการอัปเดตเพียงคอลัมน์เดียวต่อแถวที่ตรงกัน (ตารางที่จะอัปเดตเข้าร่วมกับอีกคอลัมน์หนึ่งในแบบสอบถาม) จำนวนแถวที่จะอัปเดตจะแตกต่างกันมากที่สุดอาจเป็นหลายสิบหรือหลายร้อย ฉันเชื่อว่ามีการจัดทำดัชนีสำหรับเงื่อนไขการเข้าร่วม

คำตอบ:


26

หากคุณระบุคอลัมน์ควรได้รับการอัปเดตคอลัมน์นั้นจะได้รับการอัปเดตอยู่เสมอแต่คุณสามารถเปลี่ยนค่าที่คุณใส่ไว้ในเงื่อนไขและนำค่าเดิมกลับคืนมาโดยขึ้นอยู่กับเงื่อนไขของคุณ สิ่งที่ต้องการ:

UPDATE some_table
SET    column_x = CASE WHEN should_update_x THEN new_value_for_x ELSE column_x END
     , column_y = CASE WHEN should_update_y THEN new_value_for_y ELSE column_y END
     , column_z = CASE WHEN should_update_z THEN new_value_for_z ELSE column_z END
FROM   ...

ดังนั้นหากเงื่อนไขไม่เหมาะสมสำหรับการอัปเดตคอลัมน์ใดคอลัมน์หนึ่งคุณเพียงป้อนกลับเป็นค่าปัจจุบัน

โปรดทราบว่าทุกแถวที่ตรงกันจะเห็นการอัปเดต (แม้ว่าคอลัมน์ทั้งหมดจะจบลงด้วยการตั้งค่าเป็นค่าที่พวกเขามีอยู่แล้ว) เว้นแต่คุณจะระบุสถานการณ์นี้อย่างชัดเจนในตัวกรองของคุณและอนุประโยคซึ่งอาจเป็นปัญหาประสิทธิภาพ เป็นการเขียนดัชนีจะถูกปรับปรุงทริกเกอร์ที่เหมาะสมจะเริ่มทำงาน ... ) หากไม่ได้รับการผ่อนปรน


ขอบคุณสำหรับเคล็ดลับเกี่ยวกับทุกสิ่งที่ได้รับการอัปเดตหากช้าฉันอาจทำตามคำแนะนำของ @Colin 't Hart เพื่อให้มีคำสั่งอัปเดตหลายรายการ
นิวแลนด์แลนเดอร์

คุณสามารถบรรเทาปัญหานั้นได้โดยการทำให้แน่ใจว่าประโยค ON และ WHERE ของคุณกรองแถวทั้งหมดที่ไม่ต้องการการเปลี่ยนแปลง แต่อาจหมายถึงการทำซ้ำเงื่อนไขทั้งหมดของคุณทั้งใน SET clause และ WHERE clause (เว้นแต่จะมีการตรวจสอบโดยรวมที่ง่ายกว่า) เท่ากับ 100% กับเงื่อนไขทั้งหมดที่รวมกัน) ณ จุดนี้วิธีนี้อาจยังมีประสิทธิภาพมากกว่า แต่วิธีการอัปเดตหลายวิธีอาจทำได้ง่ายกว่า
David Spillett

โปรดทราบด้วยว่าการอัปเดตคอลัมน์เป็นค่าเดียวกันจะทำให้เกิดการทำซ้ำอีกครั้งดูorainternals.wordpress.com/2010/11/04/…
Colin 't Hart

@Colin: ใช่การอัปเดตใด ๆ จะส่งผ่านบันทึกธุรกรรมของ DB รวมถึงการอัปเดตที่เป็นปัจจุบัน NoOps เนื่องจากการอัปเดตฟิลด์เพื่อให้มีค่าเดียวกันกับที่เคยมีมา เช่นเดียวกับความเป็นไปได้สำหรับปัญหาด้านประสิทธิภาพการทำงานในทันทีซึ่งอาจเป็นปัจจัยสำคัญหากใช้การจำลองแบบการสำรองข้อมูลที่แตกต่างกันการจัดส่งบันทึกและอื่น ๆ เนื่องจากการดำเนินการปรับปรุงแถวเพิ่มเติมจะเพิ่มพื้นที่ / แบนด์วิดท์ที่จำเป็น
David Spillett

ขอขอบคุณคุณทั้งสองสำหรับเคล็ดลับในกรณีของฉันคำสั่งการปรับปรุงเดียวทำงานได้ดี
newenglander

5

คุณมีชุดค่าผสมของคอลัมน์ที่จะอัปเดตจำนวนเท่าใด จะมีการอัปเดตแถวทั้งหมดกี่แถว มีการจัดทำดัชนีเพื่อให้เข้าถึงแถวเพื่ออัปเดตได้อย่างรวดเร็วหรือไม่

ขึ้นอยู่กับคำตอบสำหรับคำถามเหล่านี้คุณอาจสามารถดำเนินการหลาย ๆ คำสั่งการปรับปรุงหนึ่งคำสำหรับแต่ละคอลัมน์ที่คุณต้องการอัปเดตและวางเงื่อนไขกับมูลค่าของคอลัมน์นั้นในส่วนคำสั่งของการอัปเดตเพื่อให้แถวศูนย์ปรับปรุงถ้าคอลัมน์นั้น มีค่าที่ผิด

ลองและคิดตามการตั้งค่าอย่าคิดว่าการอัปเดตจำเป็นต้องอัปเดตแถวเดียวที่พบโดยคีย์หลัก


ขอบคุณสำหรับคำตอบ. ฉันได้เพิ่มข้อมูลเพิ่มเติมลงในคำถามของฉันฉันหวังว่าจะเข้าใจได้ นั่นเป็นทางเลือกที่ดีพร้อมด้วยคำสั่งการอัปเดตหลายรายการ (ฉันต้องการคำสั่งอัปเดตเดียว แต่ฉันเห็นว่ามีข้อได้เปรียบอยู่ที่นั่น)
นิวแลนด์แลนเดอร์

นี่อาจเป็นคำตอบที่ฉันกำลังมองหา แต่คุณต้องการใส่การปรับปรุง column_x = new_value_for_x โดยที่ @val = 0 ฉันอาจทดลองกับสิ่งนี้ ดูตลก ไม่ง่ายกว่าถ้า val = 0 เริ่มอัปเดต column_x = new_value_for_x เป็นต้น
CashCow

-1
update Practicing  -- table you will be updating
 set email = case -- column you will be updating
    when FName = 'Glenn' then 'Ace@Assasin.com'
       when FName = 'Riddick' then 'fallguy@Drunk.com'
       when FName = 'Jeffrey' then 'sorcerer@wizcom'
       else email
    end

การปรับปรุงนี้เป็นเพียงคอลัมน์เดียวในขณะที่ผู้ถามต้องการทราบวิธีการอัปเดตคอลัมน์ที่แตกต่างกันขึ้นอยู่กับเงื่อนไข
โคลิน 't ฮาร์ต
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.