在动态 SQL 中使用局部变量不起作用

Using local variable inside dynamic SQL does not work

此静态查询使用参数 returns 一行:

DECLARE @sqltext nvarchar(max)
DECLARE @status varchar(100)
SET @status = 'Active: Complete'

select * from status where StatusTitle = @status and type_id = 800

但是,如下所示在动态 SQL 查询中使用参数不会 return 任何行:

SET @sqltext = 'SELECT s.StatusID
FROM   [Status] s
WHERE  (
( s.StatusTitle ='' + @status + '' )
AND s.[type_id] = 800  )'

EXECUTE sp_executesql @sqltext

我知道 WHERE 子句有问题。我不知道如何更正它。

您需要将 @status 格式化为语句。使用 sp_executesql 执行语句会创建一个新范围,并且来自另一个范围的局部变量将不可见。

在您的声明中,您可以通过在 @status 周围添加额外的引号来解决这个问题。但是要防范SQL注入,首先需要将@status.

中的单引号换成两个单引号
SET @status=REPLACE(@status,'''','''''');
SET @sqltext = 'SELECT s.StatusID
FROM   [Status] s
WHERE  (
( s.StatusTitle =''' + @status + ''' )
AND s.[type_id] = 800  )'

EXECUTE sp_executesql @sqltext;

更好的方法是为 sp_executesql 提供一个 INPUT 参数。这样就不需要额外的引号和东西,并且可以保证防止 SQL 注入。

SET @sqltext = 'SELECT s.StatusID
FROM   [Status] s
WHERE  (
( s.StatusTitle = @status )
AND s.[type_id] = 800  )'

EXECUTE sp_executesql @sqltext, N'@status VARCHAR(100)', @status;

这也将使您免于 sql 注射

DECLARE @sqltext nvarchar(max)
DECLARE @status varchar(100)
SET @status = 'Active: Complete'
SET @sqltext = 'SELECT s.StatusID
FROM   [Status] s
WHERE  (
( s.StatusTitle = @status )
AND s.[type_id] = 800  )'

DECLARE @params NVARCHAR(99)
SET @params = '@status nvarchar(99)'

EXECUTE sp_executesql @sqltext, @params, @status

您在查询中遗漏了一对单引号,因此您的查询应该类似于

SET @sqltext = 'SELECT s.StatusID
FROM   [Status] s
WHERE  (
( s.StatusTitle =''' + @status + ''' )
AND s.[type_id] = 800  )'

EXECUTE(@sqltext)

如果您正在使用执行 sp_executesql(强制语句缓存),那么您必须使用以下查询

SET @sqltext = 'SELECT s.StatusID
FROM   [Status] s
WHERE  (
( s.StatusTitle = @status )
AND s.[type_id] = 800  )'

EXECUTE sp_executesql @sqltext, N'@status NVARCHAR(100)', @status;

最佳做法是使用 sp_executesql 然后您可以限制 sql 注入

注:

sp_executesql

的优点

1.Allows 对于要参数化的语句。

2.Has 强类型 variables/parameters – 这可以减少注入并提供一些性能优势!

3.Creates第一次执行的计划(类似于存储过程)和后续执行重用这个计划

注意 2:问题已经有了有效的答案,我希望也使用 execute 方法和 none 提到的答案,所以我也将其包含在我的答案中