T-SQL: การใช้ CASE ในคำสั่ง UPDATE เพื่ออัปเดตคอลัมน์บางคอลัมน์ขึ้นอยู่กับเงื่อนไข


108

ฉันสงสัยว่าเป็นไปได้หรือไม่ ฉันต้องการอัปเดตคอลัมน์ x หากเงื่อนไขเป็นจริงมิฉะนั้นคอลัมน์ y จะได้รับการอัปเดต

UPDATE table SET
     (CASE (CONDITION) WHEN TRUE THEN columnx
                       ELSE columny
      END)
= 25

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


สมมติว่าทั้งหมดอยู่ในตารางเดียวกันใช่ คุณสามารถเรียกใช้ในธุรกรรมได้ตลอดเวลาและย้อนกลับเมื่อเกิดข้อผิดพลาดเพื่อดูตัวคุณเอง
OMG Ponies

ฉันไม่แน่ใจว่าคุณหมายถึงอะไร ฉันได้ลองวางเงื่อนไขสำหรับคอลัมน์แล้ว แต่ไม่ได้ผล มันใช้งานได้กับคำสั่ง select แต่ไม่ใช่สำหรับคำสั่ง update (เลือก (case (condition) เมื่อเป็นจริงแล้ว columnx else columny end) จาก myTable .... การอัปเดตไม่ทำงานและฉันสามารถดูว่าทำไมมี ' ดูเหมือนวิธีที่จะทำให้มันได้ผล
pqsk

คำตอบ:


188

คุณไม่สามารถใช้เงื่อนไขเพื่อเปลี่ยนโครงสร้างของแบบสอบถามของคุณได้เฉพาะข้อมูลที่เกี่ยวข้อง คุณสามารถทำได้:

update table set
    columnx = (case when condition then 25 else columnx end),
    columny = (case when condition then columny else 25 end)

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

วิธีเดียวที่จะทำเฉพาะสิ่งที่คุณต้องการคือการใช้ไดนามิก SQL อย่างไรก็ตามนี่คือสิ่งที่ฉันขอแนะนำให้คุณอยู่ห่าง ๆ วิธีแก้ปัญหาข้างต้นเกือบจะเพียงพอสำหรับสิ่งที่คุณต้องการ


ฉันเห็นด้วยเกี่ยวกับไดนามิก SQL ข้อมูลของฉันจะได้รับผลกระทบหรือไม่ ฉันหมายความว่าฉันไม่ต้องการให้มันเปลี่ยนแปลงด้วยเงื่อนไขบางประการ แล้วมันจะใส่สิ่งที่อยู่ในนั้นเข้าไปใหม่อีกครั้ง? จำนวนครั้งที่เข้าสู่ db อาจไม่เลวร้ายนัก
pqsk

@pqsk: สิ่งนี้ไม่ควรส่งผลกระทบต่อข้อมูลของคุณ แต่ควรใส่สิ่งที่มีอยู่แล้วเข้าไปใหม่สำหรับคอลัมน์ใดก็ตามที่ไม่ควรได้รับผลกระทบ
Adam Robinson

ขอบคุณ. ฉันจะไปกับสิ่งนี้ ง่ายมากแม้แต่มนุษย์ถ้ำก็ทำได้ ฮ่า ๆ .
pqsk

1
@AdamRobinson 1.5 ปีผ่านไปคุณรู้วิธีที่มีประสิทธิภาพมากขึ้นในการอัปเดตเพียงคอลัมน์เดียว

@Somebodyisintrouble: วิธีเดียวที่จะอัปเดตคอลัมน์เดียวคือการใช้แบบสอบถามอื่น
Adam Robinson

23
UPDATE  table
SET     columnx = CASE WHEN condition THEN 25 ELSE columnx END,
        columny = CASE WHEN condition THEN columny ELSE 25 END

1
คุณแค่คัดลอกคำตอบของอดัมหรือว่านำมาจากที่อื่น? ฮ่า ๆ . เพิ่งสังเกตว่า.
pqsk

1
@pqsk: คำตอบของเราห่างกันประมาณ 1 นาทีดังนั้นฉันคิดว่าฉันเพิ่งคลิกส่งเร็วขึ้นเล็กน้อย)
Adam Robinson

23
@pqsk: ใช่ฉันเพิ่งคัดลอกคำตอบของอดัมไม่23กี่วินาทีก่อนที่เขาจะโพสต์ ฉันเป็นนักลอกแบบเร็วคนหนึ่ง!
Quassnoi

2
@pqsk: หากคุณวางเคอร์เซอร์ไว้เหนือเคอร์เซอร์* min agoจะแสดงเวลาที่แน่นอนที่โพสต์
Quassnoi

2
เพื่อความเป็นธรรมแม้ว่าทั้งสองอย่างจะเหมือนกัน: ถ้าอดัมจะออกมาตามคุณเขาก็ทำรายละเอียดเพิ่มเติม นั่นเป็นเหตุผลที่ฉันทำเครื่องหมายว่าเขาเป็นคำตอบ ขอบคุณมาก
pqsk

4

ใส่คำอธิบายภาพที่นี่

ฉันต้องการเปลี่ยนหรืออัปเดต ContactNo ของฉันเป็น 8018070999 โดยที่ 8018070777 ใช้คำสั่ง Case

update [Contacts] set contactNo=(case 
when contactNo=8018070777 then 8018070999
else
contactNo
end)

ใส่คำอธิบายภาพที่นี่


1
ทำไมไม่ใช้แบบสอบถามนี้ UPDATE [Contacts] SET contactNo = 8018070999 WHERE contactNo = 8018070777
NewGuy


1

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

IF (CONDITION) IS TRUE
BEGIN
    UPDATE table SET columnx = 25
END
ELSE
BEGIN
    UPDATE table SET columny = 25
END

ตอนนี้มีข้อดีอีกอย่างคือไม่มีการเขียนบนโต๊ะโดยไม่จำเป็นเหมือนวิธีแก้ปัญหาข้างต้น


นี่คือจุดดีและทางเลือกที่ดี! ฉันไม่ได้ใช้รหัสเดิมที่นำไปสู่เธรดนี้อีกต่อไป แต่ฉันก็มีวิธีแก้ปัญหาที่แตกต่างกันและฉันคิดว่านี่เป็นทางออกที่ดี
pqsk

-1

ฉันเชื่อว่าคุณสามารถละเว้นการอัปเดตคอลัมน์ "ที่ไม่ต้องการ" ได้โดยปรับคำตอบอื่น ๆ ดังนี้:
update table set columnx = (case when condition1 then 25 end), columny = (case when condition2 then 25 end)

ตามที่ฉันเข้าใจแล้วสิ่งนี้จะอัปเดตเมื่อตรงตามเงื่อนไขเท่านั้น

หลังจากอ่านความคิดเห็นทั้งหมดแล้วสิ่งนี้มีประสิทธิภาพมากที่สุด:
Update table set ColumnX = 25 where Condition1 Update table set ColumnY = 25 where Condition1

ตารางตัวอย่าง:
CREATE TABLE [dbo].[tblTest]( [ColX] [int] NULL, [ColY] [int] NULL, [ColConditional] [bit] NULL, [id] [int] IDENTITY(1,1) NOT NULL ) ON [PRIMARY]
ข้อมูลตัวอย่าง:
Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 0) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (null, null, 1) Insert into tblTest (ColX, ColY, ColConditional) values (1, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (2, null, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 1, null) Insert into tblTest (ColX, ColY, ColConditional) values (null, 2, null)

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

ตอนนี้การเรียกใช้โค้ดสองบรรทัดนี้จะเปลี่ยน infact X เป็น 25 ถ้า ColConditional เป็น True (1) และ Y ถึง 25 ก็ต่อเมื่อ ColConditional เป็นเท็จ (0)

Update tblTest set ColX = 25 where ColConditional = 1 Update tblTest set ColY = 25 where ColConditional = 0

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


1
สิ่งนี้ใช้ไม่ได้จริง สำหรับคอลัมน์หนึ่งถ้าคอลัมน์อนุญาตให้มีค่าว่างดังนั้นเมื่อไม่ตรงตามเงื่อนไขจะมีการกำหนดค่า null ในกรณีที่ไม่อนุญาตให้ใช้ null การอัปเดตจะล้มเหลว แบบสอบถาม "ประสิทธิภาพ" สุดท้ายของคุณไม่ถูกต้อง sql อย่างน้อยใน TSQL คุณทดสอบสิ่งนี้กับเครื่องยนต์เฉพาะและได้ผลสำหรับคุณหรือไม่?
pqsk

ฉันทดสอบสิ่งนี้บน SQL Server 2005 และทำงานได้อย่างสมบูรณ์ดังที่แสดง ฉันต้องการทราบว่าเหตุใดจึงมีการลงคะแนนและตัวอย่างที่แสดงค่า NULL ที่ได้รับการอัปเดตเนื่องจากในการทดสอบด้านบนค่า null จะไม่อัปเดต ฉันคิดเสมอว่าคำตอบที่ง่ายที่สุดคือสิ่งที่ดีที่สุดและถ้าฉันกำลังจัดการกับฐานข้อมูลที่มีระเบียนนับล้านฉันแน่ใจว่าไม่ต้องการอัปเดตแถวที่ไม่จำเป็น
John Greiner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.