我有一个任务是建立一个查询(只有where子句)并将其存储在数据库中,然后由一个存储程序执行。
我想使用参数化的动态查询,但是在DB中把查询和参数分开存储,在SQL中同时读取这两个参数,并把参数和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个占位符,或者为所有可能的参数类型创建一个带列的表,然后用coalesce得到正确的值。
我想说的是你做错了一件事,那就是你的数据库中的
exec(@sql)
指令本身并没有错,但你会受到SQL注入的攻击。 有人可以很容易地放入'select * from thing DROP TABLE Orders'。 如果那个人有权限,他们就会把你的表丢掉。 一个更好的方法是
exec sp_executesql @sql
sp_executesql也可以接受一个选项参数params,这就更加灵活了。
另外请记住,如果你说 "我使用.NET",Linq有一些很酷的东西,它可以通过模型层将SQL从数据库中抽象出来,你也可以做动态Linq。 这提供了一个抽象层,在SQL之上工作,这是优选的方式,你可以用.NET枚举和列表来模拟你的数据,以及从一个不直接连接到你的数据库的层通过整个过程运行其他代码。
是的,我们可以在动态查询中使用执行@sql。当你使用动态查询进行动态搜索时,建立一个不允许使用单引号'的regex模式,以防止sql注入。