在动态 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 提到的答案,所以我也将其包含在我的答案中
此静态查询使用参数 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 提到的答案,所以我也将其包含在我的答案中