คำสั่ง SQL Server CASE ประเมินเงื่อนไขทั้งหมดหรือออกจากเงื่อนไขแรกของ TRUE หรือไม่


44

คำสั่ง SQL Server (2008 หรือ 2012 โดยเฉพาะ) CASEประเมินWHENเงื่อนไขทั้งหมดหรือไม่หรือออกเมื่อพบWHENประโยคที่ประเมินว่าเป็นจริงหรือไม่? หากผ่านเงื่อนไขทั้งชุดนั่นหมายความว่าเงื่อนไขสุดท้ายที่ประเมินเป็นจริงจะเขียนทับเงื่อนไขแรกที่ประเมินว่าเป็นจริงหรือไม่ ตัวอย่างเช่น:

SELECT
    CASE
        WHEN 1+1 = 2 THEN'YES'
        WHEN 1+1 = 3 THEN 'NO'
        WHEN 1+1 = 2 THEN 'NO' 
    END

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


5
เกี่ยวข้องอย่างใกล้ชิดมาก: SQL Server อ่านฟังก์ชัน COALESCE ทั้งหมดแม้ว่าอาร์กิวเมนต์แรกไม่ใช่ NULL หรือไม่ (ดังที่COALESCE()แปลเป็นCASEนิพจน์)
ypercubeᵀᴹ

คำตอบ:


46

•ส่งกลับ result_expression ของแรก input_expression = when_expression ที่ประเมินเป็น TRUE

การอ้างอิง http://msdn.microsoft.com/en-us/library/ms181765.aspx


นี่คือพฤติกรรมของ SQL มาตรฐาน:

  • CASEแสดงออกประเมินสภาพจริงครั้งแรก

  • หากไม่มีเงื่อนไขจริงก็จะประเมินELSEส่วน

  • ถ้าไม่มีสภาพจริงและไม่มีส่วนก็ประเมินELSENULL


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

15

SQL Server มักจะทำการประเมินการลัดวงจรสำหรับคำสั่ง CASE ( SQLFiddle ):

--Does not fail on the divide by zero.
SELECT 
   CASE 
      WHEN 1/1 = 1 THEN 'Case 1'
      WHEN 2/0 = 1 THEN 'Case 2'
   END;

--Fails on the divide by zero.
SELECT 
   CASE 
      WHEN 1/1 = 99 THEN 'Case 1'
      WHEN 2/0 = 99 THEN 'Case 2'
   END;  

อย่างไรก็ตามมีหลายประเภทของงบที่เป็นของ SQL Server 2012 ทำลัดวงจรอย่างถูกต้อง ดูลิงค์จาก ypercube ในความคิดเห็น

Oracle ทำการประเมินการลัดวงจรเสมอ ดู11.2 SQL อ้างอิงภาษา หรือเปรียบเทียบสิ่งต่อไปนี้ ( SQLFiddle ):

--Does not fail on the divide by zero.
SELECT
  CASE 
    WHEN 1/1 = 1 THEN 'Case 1'
    WHEN 2/0 = 1 THEN 'Case 2'
  END
FROM dual;


--Fails on the divide by zero.
SELECT
  CASE 
    WHEN 1/1 = 99 THEN 'Case 1'
    WHEN 2/0 = 99 THEN 'Case 2'
  END
FROM dual;

การทดสอบเดียวกันนี้ไม่สามารถทำได้กับ MySQL เพราะมันจะคืนค่า NULL ให้หารด้วยศูนย์ ( ซอ Fiddle )


แล้วเรื่องนี้
ล่ะ

1
ซอเป็นเรื่องเกี่ยวกับ SQL เป็นคำตอบของ Aaron ที่นี่: SQL Server อ่านฟังก์ชัน COALESCE ทั้งหมดแม้ว่าอาร์กิวเมนต์แรกไม่ใช่ NULL หรือไม่
ypercubeᵀᴹ

@ypercube นั่นเป็นพฤติกรรมที่น่าสนใจจริงๆ มันกำลังประเมินโค้ดที่จะทำงานในส่วนอื่น แต่ดูเหมือนว่าจะไม่สนใจมันขึ้นอยู่กับว่ามีนิพจน์อื่น ๆ อยู่เมื่อใดและการหารด้วยศูนย์อยู่ภายใน MIN หรือไม่ ดูsqlfiddle.com/#!6/d41d8/4468
Leigh Riffel

@ypercube ตอนนี้ฉันได้อ่านลิงค์ที่คุณโพสต์แล้วคุณจะบอกว่ามีกรณีขอบเพียงพอที่จะบอกว่าคำตอบว่า SQL Server ทำการประเมินการลัดวงจรเป็นปกติหรือไม่?
Leigh Riffel

3
ใช่ฉันเห็นด้วยกับ "มักจะ" แอรอนชี้ให้เห็นคำตอบของเขาการทดสอบเพียงครั้งเดียวก็เพียงพอที่จะพิสูจน์ว่า "กรณีลัดวงจรเสมอ" แต่มันก็มักจะ
ypercubeᵀᴹ

7

ปรากฏว่า MS SQL Server ใช้การประเมินการลัดวงจรเช่นกัน

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

CREATE TABLE casetest (test varchar(10))
GO
INSERT INTO casetest VALUES ('12345'),('abcdef')
GO

SELECT CASE WHEN LEN(test)>1 THEN test
        WHEN 1/0 = 1 THEN 'abc'
        WHEN CAST(test AS int) = 1 THEN 'def'
        END
FROM casetest
GO

1

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

declare @tbl table(id int)
insert into @tbl values(1)
insert into @tbl values(2)
insert into @tbl values(3)

--Fails on the divide by zero.
SELECT * FROM @tbl
where  CASE 
        WHEN id = 2 THEN 1 -- first row in table will not satisfy the condition
        WHEN 2/0 = 1 THEN 1
        ELSE 0
      END =1

-- when filter the records to only who will staisfy the first case when condition, it 
will not fail on the divide by zero
SELECT * FROM @tbl
where ID=2 and -- first row in table will  satisfy the condition
  CASE 
    WHEN id = 2 THEN 1
    WHEN 2/0 = 1 THEN 1
    ELSE 0
  END =1

1

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


คำถามเกี่ยวกับ SQL Server
James Anderson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.