การเปรียบเทียบค่า NULL ด้วยตนเองในตาราง


13

ฉันมักจะสับสนเกี่ยวกับพฤติกรรม t-sql ลึกลับบางอย่างเช่นต่อไปนี้

-- Create table t and insert values.  
use tempdb
CREATE TABLE dbo.t (a INT NULL);  
-- insert 3 values
INSERT INTO dbo.t values (NULL),(0),(1);  
GO  
set ansi_nulls off -- purposely turn off, so we can allow NULL comparison, such as null = null
go
-- expect 3 rows returned but only 2 returned (without null value row)
select * from dbo.t where a = a 

สิ่งนี้ไม่เกี่ยวกับวิธีดึงแถวทั้งหมดในตารางและไม่เกี่ยวกับการหลีกเลี่ยงการใช้ ANSI_NULLS

ฉันแค่ต้องการเรียกดูข้อมูลเชิงลึกบางอย่างว่าทำไม t-sql ทำงานแบบนี้

คำตอบ:


13

นี่เป็นพฤติกรรมที่น่าประหลาดใจ แต่จากหน้า MSDN SET ANSI_NULLSเราอย่างน้อยก็รู้ได้ว่ามันเป็นพฤติกรรมที่คาดหวัง อีกเหตุผลหนึ่งที่ไม่เคยใช้ANSI_NULLS OFF:

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


8

แม้ว่ามันอาจจะไม่ชัดเจนจากเอกสาร msdn แต่ฉันเชื่อว่าคุณจะพบสิ่งต่อไปนี้เป็นจริง

"SET ANSI_NULLS ON มีผลต่อการเปรียบเทียบเฉพาะเมื่อตัวถูกดำเนินการหนึ่งในการเปรียบเทียบเป็นตัวแปรที่เป็น NULL หรือ NULL ตามตัวอักษรหากทั้งสองด้านของการเปรียบเทียบเป็นคอลัมน์หรือนิพจน์แบบผสมการตั้งค่าจะไม่มีผลต่อการเปรียบเทียบ"

ดู/programming/2866714/how-does-ansi-nulls-work-in-tsqlนี้


ขอบคุณ Scott และ ypercube ทั้งคำตอบของคุณคือสิ่งสำคัญสำหรับพฤติกรรมนี้ดังนั้นฉันจึง upvote ทั้งคำตอบของคุณ
jyao

Ypercube เป็นคนแรก :)
Scott Hodgin

4

Robert Sheldon ในโพสต์ต่อไปนี้จากปี 2558 อธิบายพฤติกรรม NULL และสาเหตุที่ทำให้บางครั้งพวกเขา (แต่ไม่เสมอไป) ล้มเหลว

https://www.simple-talk.com/sql/t-sql-programming/how-to-get-nulls-horribly-wrong-in-sql-server/

เขาอธิบายความล้มเหลวของ NULL 13 ครั้งที่โปรแกรมเมอร์สามารถเดินทางข้ามได้อย่างง่ายดาย

ความล้มเหลว # 1: ไม่ทราบว่าค่า NULL หมายถึงอะไร

คำอธิบาย: NULL เป็นค่าที่ไม่ใช่ค่าที่ไม่มีอยู่ มันไม่ได้เป็นศูนย์ มันไม่ใช่สตริงว่างเปล่า ค่าต้องไม่เท่ากับ NULL ไม่มีสองค่าเป็นศูนย์มีค่าเท่ากัน

นั่นคือปัญหาพื้นฐาน แต่อย่าลืมอ่านข้อผิดพลาดอื่น ๆ

ใช่เวอร์ชันก่อนหน้า (เชื่อว่า pre-SQL Server 7) มีพฤติกรรมแตกต่างกันมากกว่าที่คุณต้องการ

อย่างไรก็ตามหากคุณค้นหาปัญหาใน Stack Overflow และ Stack Exchange คุณจะพบกระทู้จำนวนมากที่พูดถึงปัญหา


3
ฉันเคยอ่านโพสต์ที่เชื่อมโยงจาก Robert Sheldon แต่ไม่มี (IMHO) มีทฤษฎีหรือหลักฐานใด ๆ ที่อธิบายพฤติกรรมของตัวอย่างของฉัน
jyao

1
"ไม่มีค่า NULL สองค่าเท่ากัน" ตกลง แต่คนที่รู้ว่าจะคาดหวังตรงกันข้ามเมื่อ ansi โมฆะถูกตั้งค่าเป็นปิด โดยเฉพาะอย่างยิ่งเพราะWHERE NULL = NULLให้ผลจริงเมื่อตั้งค่าเป็น
ypercubeᵀᴹ

1

เพื่อเพิ่มการสนทนาคำจำกัดความมาตรฐานของ NULL ของSQL92สามารถตีความได้อย่างคลุมเครือ นี่เป็นบทสรุปที่ดีของการจัดการ NULL และการตีความจาก DBMS ที่ได้รับความอนุเคราะห์จาก sqlite.org

การเปิดเผยข้อมูล : ฉันจำได้ว่าเคยอ่านเกี่ยวกับ "ความกำกวม" ของ SQL92 จากเวอร์ชั่นเก่ากว่า (เช่น 6-8 ปีก่อน) ของหน้า sqlite.org ที่ลิงก์ด้านบน แต่หน้านั้นได้รับการปรับปรุงตั้งแต่

คำตอบของ RLF ด้านบนมีคำพูดที่ดี แต่ถ้าฉันไม่เห็นด้วยกับ Robert Sheldon เพียงเพราะฉันคิดว่า "สิ่งที่ไม่มีอยู่" (เช่นNULL ) เป็นปรัชญาและภาษาอังกฤษ - ภาษา - ความหมายเทียบเท่ากับ "สิ่งอื่นที่ไม่มีอยู่จริง" " ถ้าฉันเข้าใจตรรกะของเชลดอนใครก็สามารถประกาศนิยามของ NULL ได้เช่นกัน (หากไม่มีอยู่แล้วเราจะกำหนดมันได้อย่างไรน่าขนลุกใช่มั้ย)

ฉันเห็นการเปลี่ยนแปลงของการผลิตเบียร์ของ Paradox ของรัสเซล ( และปวดหัว) : - \

แต่ครั้งนี้เป็นการอภิปรายเกี่ยวกับความหมายภาษาอังกฤษ ( ไม่ SQL) และการอภิปรายปรัชญาเป็นมากกว่าที่นี่ :-)


ป.ล. ฉันใหม่ที่นี่เพื่อชุมชน SE นี้; ถ้าสิ่งนี้ได้ถูกกล่าวถึงอาการคลื่นไส้โฆษณามาก่อนแล้วฉันต้องขออภัย
pr1268

1
ความกำกวมในมาตรฐานอยู่ที่ไหน?
ypercubeᵀᴹ

@ ypercubeᵀᴹ: ฉันเชื่อว่าความคลุมเครืออยู่ในความพยายามที่จะ "ปรับ" 3VLให้เป็นบูลีน การรวมตารางที่มีการเปรียบเทียบค่า NULLสามารถตีความได้หลายวิธี
pr1268

ฉันจะเห็นด้วยเกี่ยวกับความไม่สอดคล้องกัน แต่ไม่เกี่ยวกับความกำกวม
ypercubeᵀᴹ

1
@ ypercubeᵀᴹ: ยุติธรรมพอ ... ฉันแค่อ้างถึงหน้า sqlite.org รุ่นเก่าที่ฉันลิงค์ไว้ด้านบนกล่าวว่า ("SQL92 นั้นคลุมเครือเกี่ยวกับการจัดการและตีความ NULL" หรือบางอย่างที่คล้ายกันมาก) แต่ฉันไม่ได้ตั้งใจจะเถียง บางทีหน้า sqlite.org อาจทำให้เข้าใจผิดและ / หรือผิดพลาดทั้งหมด ซึ่งน่าจะอธิบายได้ว่าทำไมมันถึงได้รับการอัพเดท
pr1268
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.