รูปแบบนี้
column = @argument OR (@argument IS NULL AND column IS NULL)
สามารถถูกแทนที่ด้วย
EXISTS (SELECT column INTERSECT SELECT @argument)
สิ่งนี้จะช่วยให้คุณจับคู่ค่า NULL กับค่า NULL และอนุญาตให้เอ็นจิ้นใช้ดัชนีcolumn
อย่างมีประสิทธิภาพ สำหรับการวิเคราะห์เชิงลึกที่ยอดเยี่ยมของเทคนิคนี้ฉันแนะนำคุณไปยังบทความบล็อกของ Paul White:
เนื่องจากมีข้อโต้แย้งสองข้อในกรณีเฉพาะของคุณคุณสามารถใช้เทคนิคการจับคู่แบบเดียวกันด้วย@Blah
วิธีนี้คุณจะสามารถเขียน WHERE ทั้งหมดอีกครั้งโดยย่อหรือกระชับ
WHERE
EXISTS (SELECT a.Blah, a.VersionId INTERSECT SELECT @Blah, @VersionId)
(a.Blah, a.VersionId)
นี้จะทำงานได้อย่างรวดเร็วด้วยดัชนีใน
หรือเครื่องมือเพิ่มประสิทธิภาพข้อความค้นหาทำให้เป็นหลักเหมือนกันหรือไม่
ในกรณีนี้ใช่ ในทุกรุ่น (อย่างน้อย) จาก SQL Server 2005 เป็นต้นไปเครื่องมือเพิ่มประสิทธิภาพสามารถจดจำรูปแบบcol = @var OR (@var IS NULL AND col IS NULL)
และแทนที่ด้วยการIS
เปรียบเทียบที่เหมาะสม สิ่งนี้ขึ้นอยู่กับการจับคู่การเขียนซ้ำภายในดังนั้นอาจมีกรณีที่ซับซ้อนมากกว่านี้ซึ่งไม่น่าเชื่อถือเสมอไป
ในรุ่นของ SQL Server ตั้งแต่ 2008 SP1 CU5คุณยังมีตัวเลือกในการใช้การเพิ่มประสิทธิภาพการฝังพารามิเตอร์ด้วยOPTION (RECOMPILE)
โดยที่ค่ารันไทม์ของพารามิเตอร์หรือตัวแปรใด ๆ จะถูกฝังในแบบสอบถามเป็นตัวอักษรก่อนการรวบรวม
ดังนั้นอย่างน้อยถึงขนาดใหญ่ในกรณีนี้การเลือกเป็นเรื่องของสไตล์แม้ว่าการINTERSECT
ก่อสร้างจะมีขนาดกะทัดรัดและสง่างามอย่างปฏิเสธไม่ได้
ตัวอย่างต่อไปนี้แสดงแผนการดำเนินการ 'เดียวกัน' สำหรับแต่ละรูปแบบ (ยกเว้นตัวอักษรและการอ้างอิงตัวแปร):
DECLARE @T AS table
(
c1 integer NULL,
c2 integer NULL,
c3 integer NULL
UNIQUE CLUSTERED (c1, c2)
);
-- Some data
INSERT @T
(c1, c2, c3)
SELECT 1, 1, 1 UNION ALL
SELECT 2, 2, 2 UNION ALL
SELECT NULL, NULL, NULL UNION ALL
SELECT 3, 3, 3;
-- Filtering conditions
DECLARE
@c1 integer,
@c2 integer;
SELECT
@c1 = NULL,
@c2 = NULL;
-- Writing the NULL-handling out explicitly
SELECT *
FROM @T AS T
WHERE
(
T.c1 = @c1
OR (@c1 IS NULL AND T.c1 IS NULL)
)
AND
(
T.c2 = @c2
OR (@c2 IS NULL AND T.c2 IS NULL)
);
-- Using INTERSECT
SELECT *
FROM @T AS T
WHERE EXISTS
(
SELECT T.c1, T.c2
INTERSECT
SELECT @c1, @c2
);
-- Using separate queries
IF @c1 IS NULL AND @c2 IS NULL
SELECT *
FROM @T AS T
WHERE T.c1 IS NULL
AND T.c2 IS NULL
ELSE IF @c1 IS NULL
SELECT *
FROM @T AS T
WHERE T.c1 IS NULL
AND T.c2 = @c2
ELSE IF @c2 IS NULL
SELECT *
FROM @T AS T
WHERE T.c1 = @c1
AND T.c2 IS NULL
ELSE
SELECT *
FROM @T AS T
WHERE T.c1 = @c1
AND T.c2 = @c2;
-- Using OPTION (RECOMPILE)
-- Requires 2008 SP1 CU5 or later
SELECT *
FROM @T AS T
WHERE
(
T.c1 = @c1
OR (@c1 IS NULL AND T.c1 IS NULL)
)
AND
(
T.c2 = @c2
OR (@c2 IS NULL AND T.c2 IS NULL)
)
OPTION (RECOMPILE);