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/

相关文章:

ios - 如何在 SQLITE 中使用 AM/PM 按日期/时间排序

sql-server - T-SQL - 两个日期时间之间每小时的分钟数

sql - 从表和引用表中删除重复行 microsoft sql server

sql - 避免使用 IN 子句和 Spanner 中的子查询进行哈希连接

PHP MySQL 搜索不返回结果

mysql - 如何扫描MySQL中的多个项目?

SQL with 子句动态 where 参数

sql-server - SQL查询结果问题

SQL:除了查询

c# - 存储过程需要一个我已经传入的参数