【问题标题】:Dynamic SQL - EXEC(@SQL) versus EXEC SP_EXECUTESQL(@SQL)动态 SQL - EXEC(@SQL) 与 EXEC SP_EXECUTESQL(@SQL)
【发布时间】:2010-10-07 13:54:27
【问题描述】:

使用 SQL Server 在存储过程中执行动态 SQL 命令的实际利弊是什么

EXEC (@SQL)

EXEC SP_EXECUTESQL @SQL

?

【问题讨论】:

    标签: sql sql-server dynamic


    【解决方案1】:

    SP_EXECUTESQL 最重要的是它允许您创建参数化查询,如果您关心 SQL 注入,这非常好。

    【讨论】:

    • 我不认为没有它你可以参数化动态 sql 吗??
    • 如果动态构建查询以防止 sql 注入,这绝对是使用 sp_executesql 的最大原因之一。
    【解决方案2】:

    sp_executesql 更有可能促进查询计划重用。使用sp_executesql 时,参数在调用签名中明确标识。这篇优秀的文章描述了这个process

    动态 sql 的许多方面经常被引用的参考是 Erland Sommarskog 的必读:“The Curse and Blessings of Dynamic SQL”。

    【讨论】:

    • 请您说明为什么 sp_executesql 允许在 exec 不允许的情况下重复使用查询计划?
    【解决方案3】:
    1. 声明变量
    2. 通过您的命令设置它并添加动态部分,例如使用 sp 的参数值(这里 @IsMonday 和 @IsTuesday 是 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)
      

    【讨论】:

    • 这对 SQL 注入开放,如果你把例如“a';DROP DATABASE DATABASE_NAME; 去;';”在@IsMonday 变量中
    • 如果@IsMonday 是 int 是否容易产生 sql 指令?
    • @VikasRana @IsMonday 在动态 SQL 中不能是 int。注意@sql 被声明为varcharnvarchar
    【解决方案4】:

    微软的Using sp_executesql 文章建议使用sp_executesql 而不是execute 语句。

    因为这个存储过程支持参数替换, sp_executesql 比 EXECUTE 更通用;因为 sp_executesql 生成的执行计划更有可能是 sp_executesql 被 SQL Server 重用,比 EXECUTE更高效

    所以,要点:不要使用execute 声明。使用sp_executesql

    【讨论】:

    • 您的外卖并不总是有效。有时使用 sp_executesql 没有效率奖励,但您可以保护您的代码免受 sql 注入攻击。有时你不能像使用 exec 那样使用 sp_executesql,所以……有人说 - 没有灵丹妙药。我同意。
    • 是的,微软应该将其描述为“更可能更有效率”。在这个行业工作了几年,我看到了sp_executesql 不能用来代替execute 的情况。也许我应该把我想强调的观点说成:尽可能使用sp_executesql而不是execute
    • 请您说明为什么 sp_executesql 允许在 exec 不允许的情况下重复使用查询计划?
    【解决方案5】:

    这些天我总是使用 sp_executesql,它实际上只是一个处理参数和变量的 EXEC 的包装器。

    但是,在非常大的数据库上调整查询时不要忘记 OPTION RECOMPILE,尤其是在您的数据跨越多个数据库并使用 CONSTRAINT 来限制索引扫描的情况下。

    除非您使用 OPTION RECOMPILE,否则 SQL Server 将尝试为您的查询创建“一刀切”的执行计划,并在每次运行时运行全索引扫描。

    这比查找效率低得多,这意味着它可能会扫描整个索引,这些索引被限制在您甚至没有查询的范围内:@

    【讨论】:

      猜你喜欢
      • 2023-03-25
      • 1970-01-01
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-09
      • 1970-01-01
      相关资源
      最近更新 更多