我有一个构建查询的任务(只是where子句)并将其存储在数据库中。 然后它将由存储过程执行。
我想使用参数化的动态查询,但是将查询与DB中的参数分开存储是很尴尬的,在SQL中读取并将params绑定到where子句。重要的是参数的数量和类型是任意的。
我不希望非参数化的动态SQL因为搜索值是由用户提供的,而我找不到可靠的方法来防止SQL注入。
有一种优雅的方法吗?
我正在使用.NET和SQL Server。
我在谈论的例子:
-- @filterId is passed to the SP
declare @sql nvarchar(max)
set @sql = 'select id, name, otherField from Items where' + whereClause
from Filters
where id = @filterId
create table #items {
id int not null,
name nvarchar(100),
otherField nvarchar(200)
}
insert into #items exec(@sql)
-- do something with items and return result
编辑:我被建议避免使用主观条款以获得有意义的回复。我相信定义什么是“最好”和“优雅”会做。 因此,当我说“最佳”时,我正在寻找一种安全,快速,可读和可维护的解决方案。 “优雅” - 完成任务,使用最少的代码,没有太多的假设,例如如果我需要处理任意参数集,我不想为可能的参数创建20个占位符,或者为所有可能类型的参数创建一个包含列的表,并通过合并获得正确的值。
答案 0 :(得分:0)
我会说你做错的一件事是
exec(@sql)
对于指令本身而言,每个说法都没有错,但您可以通过SQL注入进行攻击。有人可以很容易地输入'select * from thing DROP TABLE Orders'。如果那个人有权利他们就放弃你的桌子。一个更好的方法是
exec sp_executesql @sql
确保@sql是unicode varchar,您已在示例中执行过此操作。 sp_executesql还采用了更灵活的选项params参数。
另外请记住,如果你说“我正在使用.NET”,Linq有一些很酷的东西可以用实体框架来通过模型层从数据库中抽象出SQL,你也可以做动态Linq。这提供了一个抽象层,可以使用SQL的优先级,这种方式可以通过.NET枚举和列表建模数据,以及在整个过程中从未直接连接到数据库的层运行其他代码。 / p>
答案 1 :(得分:0)
是的,我们可以在动态查询中使用execute @sql。当您使用动态查询进行动态搜索时,构建一个正则表达式模式,该模式不允许单引号'防止sql注入。