คุณอาจต้องการดูคำตอบของคำถามที่คล้ายกันนี้ที่นี่:
/programming/11329823/add-where-clauses-to-sql-dynamically-programmatically
เราพบว่า SPROC ซึ่งใช้พารามิเตอร์ตัวเลือกมากมายและใช้ตัวกรองดังนี้:
CREATE PROC MyProc (@optionalParam1 NVARCHAR(50)=NULL, @optionalParam2 INT=NULL)
AS
...
SELECT field1, field2, ... FROM [Table]
WHERE
(@optionalParam1 IS NULL OR MyColumn1 = @optionalParam1)
AND (@optionalParam2 IS NULL OR MyColumn2 = @optionalParam2)
จะแคชแผนการดำเนินการครั้งแรกที่เรียกใช้ด้วย (เช่น@optionalParam1 = 'Hello World', @optionalParam2 = NULL
) แต่จากนั้นดำเนินการอย่างน่าสังเวชถ้าเราผ่านชุดพารามิเตอร์ทางเลือกอื่น (เช่น@optionalParam1 = NULL, @optionalParam2 = 42
) (และแน่นอนว่าเราต้องการประสิทธิภาพของแผนแคชดังนั้นจึงWITH RECOMPILE
ออก)
ข้อยกเว้นที่นี่คือหากมีตัวกรอง MANDATORY อย่างน้อยหนึ่งตัวในแบบสอบถามซึ่งเลือกอย่างสูงและจัดทำดัชนีอย่างถูกต้องนอกเหนือจากพารามิเตอร์ทางเลือกแล้ว PROC ด้านบนจะทำงานได้ดี
อย่างไรก็ตามหากตัวกรองทั้งหมดเป็นตัวเลือกความจริงที่น่ากลัวกว่านั้นคือ sql แบบแปรผันตามจริงจะมีประสิทธิภาพดีกว่า (เว้นแต่คุณจะเขียน PROCS สแตติกที่แตกต่างกัน N!
SQL แบบไดนามิกด้านล่างจะสร้างและแคชแผนที่แตกต่างกันสำหรับการเปลี่ยนค่าพารามิเตอร์ Query แต่ละครั้ง แต่อย่างน้อยแต่ละแผนจะถูกปรับให้เหมาะกับการสืบค้นเฉพาะ (ไม่สำคัญว่าจะเป็น PROC หรือ Adhoc SQL หรือไม่ ตราบใดที่คำค้นหาเป็นพารามิเตอร์พวกเขาจะถูกแคช)
ดังนั้นการตั้งค่าของฉันสำหรับ:
DECLARE @SQL NVARCHAR(MAX)
-- Mandatory / Static part of the Query here
SET @SQL = N'SELECT * FROM [table] WHERE 1 = 1'
IF @OptionalParam1 IS NOT NULL
BEGIN
SET @SQL = @SQL + N' AND MyColumn1 = @optionalParam1'
END
IF @OptionalParam2 IS NOT NULL
BEGIN
SET @SQL = @SQL + N' AND MyColumn2 = @optionalParam2'
END
EXEC sp_executesql @SQL,
N'@optionalParam1 NVARCHAR(50),
@optionalParam2 INT'
,@optionalParam1 = @optionalParam1
,@optionalParam2 = @optionalParam2
ฯลฯ ไม่สำคัญว่าเราจะส่งผ่านพารามิเตอร์ที่ซ้ำซ้อนไปยัง sp_executesql หรือไม่ซึ่งจะถูกละเว้น เป็นที่น่าสังเกตว่า ORM ของ Linq2SQL และ EF ใช้พารามิเตอร์แบบไดนามิก sql ในลักษณะที่คล้ายกัน