sql - 带有 'IN' 语句的 sp_executesql

标签 sql sql-server-2005 tsql sp-executesql

我正在尝试使用 sp_executesql 来防止 SQL 2005 中的 SQL 注入(inject),我有一个像这样的简单查询:

SELECT * from table WHERE RegionCode in ('X101', 'B202')

但是,当我使用 sp_executesql 执行以下命令时,它没有返回任何内容。

Set @Cmd = N'SELECT * FROM table WHERE RegionCode in (@P1)'
SET @ParamDefinition = N'@P1 varchar(100)';
DECLARE @Code as nvarchar(100);
SET @Code = 'X101,B202'
EXECUTE sp_executesql @Cmd, @ParamDefinition, @P1 = @Code

这是我测试过的:

SET @Code = 'X101'   <-- This works, it returns a single region
SET @Code = 'X101,B202'   <--- Returns nothing
SET @Code = '''X101'',''B202'''  <-- Returns nothing

请帮忙....我做错了什么?

最佳答案

它不起作用的原因是因为@P1 被视为一个单一的值。

例如当@Code 为 X101,B202 时,查询将按以下方式运行: SELECT * FROM 表 WHERE RegionCode IN ('X101,B202') 因此,它正在寻找一个 RegionCode,其值包含在 @P1 中。即使您包含单引号,这也意味着它在 RegionCode 中搜索的值应该包含这些单引号。

您实际上需要将 @Code 变量连接到 @Cmd sql 命令文本中,以便它按照您的想法工作:

SET @Code = '''X101'',''B202'''
SET @Cmd = 'SELECT * FROM Table WHERE RegionCode IN (' + @Code + ')'
EXECUTE (@Cmd)

但很明显,这只会让您容易受到 SQL 注入(inject)攻击,因此如果您采用这种方法以确保防范这种情况,则需要非常小心。

有多种替代方法可以处理这种情况,您可以传递一个动态值列表来进行搜索。

查看 my blog 上的示例对于可以与 SQL Server 2005 一起使用的 2 种方法。一种涉及以“Value1、Value2、Value3”的形式传入 CSV 列表,然后使用用户定义的函数将其拆分为一个 TABLE 变量(很多人都提到了这个方法,如果你做一个快速谷歌或搜索这个网站)。一旦拆分出来,您就可以将该 TABLE var 加入到您的主查询中。第二种方法是传入包含值的 XML blob 并使用 SQL Server 的内置 XML 功能。这两种方法都在该链接中使用性能指标进行了演示,并且它们不需要动态 SQL。

如果您使用的是 SQL Server 2008,表值参数将是可行的方法 - 这是我在该链接中展示的第三种方法,效果最好。

关于sql - 带有 'IN' 语句的 sp_executesql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2600389/

相关文章:

sql - 传递包含空格的字符串时存储过程中出现语法错误

php - 更新后台数据库和网站

php - php数据库如何查找年龄20岁以上25岁以下的用户

c# - 将密码存储到sql中的最佳方法

sql-server - 维护存储过程——如何在不阻塞复制的情况下删除

sql - 每天的数据差异

MYSQL 内连接错误 - 'm.account_no' 中的未知列 'where clause'

sql - 为什么 `NOT IN` cte 不起作用但 `NOT IN` 子查询有效?

sql-server-2005 - 对价格和值(value)使用 varchar 而非十进制有什么好处

sql - 计算 SQL Server 中 bool 值更改的次数