คำสั่งนี้ถูกกฎหมาย (ในคำอื่น ๆ ไม่FROM
จำเป็นต้องใช้):
SELECT x = 1;
SELECT x = 1 WHERE 1 = 1; -- also try WHERE 1 = 0;
เคล็ดลับคือเมื่อคุณแนะนำชื่อคอลัมน์ที่ไม่มีอยู่จริง ดังนั้นสิ่งเหล่านี้จึงล้มเหลว:
SELECT name WHERE 1 = 1;
SELECT x = 1 WHERE id > 0;
ข่าวสารเกี่ยวกับ 207, ระดับ 16, สถานะ 1
ชื่อคอลัมน์ไม่ถูกต้อง 'ชื่อ'
ข่าวสารเกี่ยวกับ 207, ระดับ 16, สถานะ 1
ชื่อคอลัมน์ไม่ถูกต้อง 'id'
แต่เมื่อมีการนำคอลัมน์ที่ไม่ถูกต้องมาใช้ในบางสิ่งเช่นแบบสอบถามย่อยสิ่งที่ SQL Server ทำเมื่อไม่สามารถค้นหาคอลัมน์นั้นในขอบเขตด้านในของแบบสอบถามย่อยจะข้ามไปยังขอบเขตด้านนอกและทำให้แบบสอบถามย่อยสัมพันธ์กับขอบเขตด้านนอกนั้น สิ่งนี้จะส่งคืนแถวทั้งหมดตัวอย่างเช่น:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE 1 = 1);
เพราะเป็นหลักว่า:
SELECT * FROM sys.columns WHERE name IN (SELECT sys.columns.name WHERE 1 = 1); /*
^^^^^^^^^^^ -----------
| |
----------------------------------- */
คุณไม่จำเป็นต้องมีWHERE
ประโยคในแบบสอบถามย่อย:
SELECT * FROM sys.columns WHERE name IN (SELECT name);
คุณจะเห็นว่ามันกำลังดูที่ตารางที่อยู่นอกขอบเขตเพราะสิ่งนี้:
SELECT * FROM sys.columns WHERE name IN (SELECT name WHERE name > N'x');
ส่งคืนแถวที่น้อยกว่ามาก (11 ในระบบของฉัน)
เรื่องนี้เกี่ยวข้องกับการยึดมั่นกับมาตรฐานเกี่ยวกับการกำหนดขอบเขต คุณสามารถเห็นสิ่งที่คล้ายกันเมื่อคุณมี #temp สองตาราง:
CREATE TABLE #foo(foo int);
CREATE TABLE #bar(bar int);
SELECT foo FROM #foo WHERE foo IN (SELECT foo FROM #bar);
เห็นได้ชัดว่าข้อผิดพลาดนี้ควรขวาตั้งแต่ยังไม่มีfoo
ใน#bar
? Nope สิ่งที่เกิดขึ้นคือ SQL Server บอกว่า "โอ้ฉันไม่พบfoo
ที่นี่คุณต้องมีความหมายอีกอย่างหนึ่ง"
NOT IN
นอกจากนี้ในทั่วไปผมจะหลีกเลี่ยง NOT EXISTS
มีศักยภาพที่จะมีประสิทธิภาพมากขึ้นในบางสถานการณ์ NULL
แต่ที่สำคัญกว่าพฤติกรรมของมันจะไม่เปลี่ยนแปลงเมื่อเป็นไปได้ว่าคอลัมน์เป้าหมายที่อาจจะ เห็นโพสต์นี้สำหรับข้อมูลเพิ่มเติม