Dynamic SQL - EXEC (@SQL) เทียบกับ EXEC SP_EXECUTESQL (@SQL)


96

ข้อดีข้อเสียในโลกแห่งความเป็นจริงของการเรียกใช้คำสั่ง SQL แบบไดนามิกในโพรซีเดอร์ที่เก็บไว้ใน SQL Server โดยใช้

EXEC (@SQL)

เทียบกับ

EXEC SP_EXECUTESQL @SQL

เหรอ?

คำตอบ:


96

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

บ่อยครั้งที่อ้างถึงการอ้างอิงสำหรับหลายแง่มุมของไดนามิก sql เป็นสิ่งที่ต้องอ่านของ Erland Sommarskog: " The Curse and Blessings of Dynamic SQL "


21

สิ่งสำคัญเกี่ยวกับ SP_EXECUTESQL คือช่วยให้คุณสร้างการสืบค้นแบบกำหนดพารามิเตอร์ซึ่งเป็นสิ่งที่ดีมากหากคุณสนใจเกี่ยวกับการแทรก SQL


1
ฉันไม่คิดว่าคุณจะสามารถปรับแต่ง SQL แบบไดนามิกได้โดยไม่ต้องใช้มัน ??
ดีเจ.

EXEC ('SELECT * FROM FOO WHERE ID =?', 123) จะแทนที่ตัวยึดพารามิเตอร์ "?" ด้วยค่า 123 จากนั้นดำเนินการค้นหาโดยส่งคืนผลลัพธ์สำหรับ SELECT * FROM FOO WHERE ID = 123
Peter Wone

1
อ๊ะไวยากรณ์นั้นพร้อมใช้งานสำหรับเซิร์ฟเวอร์ที่เชื่อมโยงเท่านั้น
Peter Wone

1
เหตุผลที่ใหญ่ที่สุดประการหนึ่งในการใช้ sp_executesql หากสร้างแบบสอบถามแบบไดนามิกเพื่อป้องกันการฉีด sql
Steven Rogers

5

บทความการใช้ sp_executesqlของ Microsoft แนะนำให้ใช้sp_executesqlแทนexecuteคำสั่ง

เนื่องจากโพรซีเดอร์ที่เก็บไว้นี้สนับสนุนการทดแทนพารามิเตอร์ sp_executesql จึงมีความหลากหลายมากกว่า EXECUTE และเนื่องจาก sp_executesql สร้างแผนการดำเนินการที่มีแนวโน้มที่จะถูกนำกลับมาใช้โดย SQL Server sp_executesql จึงมีประสิทธิภาพมากกว่า EXECUTE

ดังนั้น Take Away: ไม่ได้ใช้executeคำสั่ง ใช้sp_executesql.


7
Takeaway ของคุณไม่เสมอไป มีบางครั้งที่ไม่มีโบนัสประสิทธิภาพโดยใช้ sp_executesql แต่คุณสามารถป้องกันรหัสของคุณจากการโจมตีด้วยการฉีด sql บางครั้งคุณไม่สามารถใช้ sp_executesql ในแบบที่คุณสามารถใช้ exec ได้ดังนั้น ... มีคนกล่าวว่า - ไม่มีกระสุนเงิน ฉันเห็นด้วย.
OzrenTkalcecKrznaric

ใช่ Microsoft ควรกำหนดให้เป็น " น่าจะมีประสิทธิภาพมากกว่า" และอยู่ในวงการมาหลายปีฉันเคยเห็นกรณีที่sp_executesqlไม่สามารถใช้ทดแทนexecuteได้ บางทีฉันควรวางจุดฉันพยายามที่จะเป็นความเครียด: ใช้sp_executesqlแทนเมื่อใดก็ตามที่เป็นไปได้execute
กันต์

2

วันนี้ฉันมักจะใช้ sp_executesql ทั้งหมดที่เป็นกระดาษห่อหุ้มสำหรับ EXEC ซึ่งจัดการพารามิเตอร์และตัวแปร

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

เว้นแต่คุณจะใช้ OPTION RECOMPILE เซิร์ฟเวอร์ SQL จะพยายามสร้างแผนการดำเนินการ "หนึ่งขนาดที่เหมาะกับทุกคน" สำหรับแบบสอบถามของคุณและจะเรียกใช้การสแกนดัชนีทั้งหมดทุกครั้งที่เรียกใช้

สิ่งนี้มีประสิทธิภาพน้อยกว่าการค้นหามากและหมายความว่ามันอาจสแกนดัชนีทั้งหมดซึ่ง จำกัด อยู่ในช่วงที่คุณไม่ได้ค้นหา: @


-2
  1. ประกาศตัวแปร
  2. ตั้งค่าตามคำสั่งของคุณและเพิ่มส่วนไดนามิกเช่นใช้ค่าพารามิเตอร์ของ sp (ที่นี่ @IsMonday และ @IsT Tuesday เป็นพารามิเตอร์ sp)
  3. ดำเนินการคำสั่ง

    declare  @sql varchar (100)
    set @sql ='select * from #td1'
    
    if (@IsMonday+@IsTuesday !='')
    begin
    set @sql= @sql+' where PickupDay in ('''+@IsMonday+''','''+@IsTuesday+''' )'
    end
    exec( @sql)
    

15
สิ่งนี้เปิดสำหรับการแทรก SQL หากคุณใส่เช่น "a '; DROP DATABASE DATABASE_NAME; GO;';" ในตัวแปร @IsMonday
Erik A. Brandstadmoen

มีแนวโน้มที่จะเกิดการบาดเจ็บของ sql หรือไม่ถ้า @IsMonday เป็น int?
Vikas Rana

@VikasRana @IsMonday ไม่สามารถintอยู่ในไดนามิก SQL โปรดทราบว่า @sql ประกาศเป็นvarcharหรือnvarchar
Weihui Guo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.