使用参数的静态查询返回一行:
DECLARE @sqltext nvarchar(max)
DECLARE @status varchar(100)
SET @status = 'Active: Complete'
select * from status where StatusTitle = @status and type_id = 800
但是,如下所示在动态SQL查询中使用该参数根本不会返回任何行:
SET @sqltext = 'SELECT s.StatusID
FROM [Status] s
WHERE (
( s.StatusTitle ='' + @status + '' )
AND s.[type_id] = 800 )'
EXECUTE sp_executesql @sqltext
我知道WHERE子句有问题。我无法弄清楚如何纠正它。
答案 0 :(得分:5)
您需要将@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;
答案 1 :(得分:3)
这也将使您免于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
答案 2 :(得分:1)
您在查询中错过了一对单引号,因此您的查询应该类似于
SET @sqltext = 'SELECT s.StatusID
FROM [Status] s
WHERE (
( s.StatusTitle =''' + @status + ''' )
AND s.[type_id] = 800 )'
EXECUTE(@sqltext)
如果您正在使用execute 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.允许语句参数化。
2.具有强类型变量/参数 - 这可以减少注入并提供一些性能优势!
3.创建首次执行计划(类似于存储过程),后续执行重用此计划
注意2:问题已经有了可行的答案,我希望使用execute也是一种方法而且没有提到的答案,所以我也在答案中包含了这个