将操作符传递给存储过程

时间:2012-10-02 13:35:44

标签: c# sql sql-server

我有一个ASP.NET MVC 3应用程序,允许用户创建自己的过滤器。像amount > 5 and amount <= 7之类的东西,等等。用户可以选择金额值和操作员。

我的问题是如何将这些过滤器传递给检索数据的存储过程。存储过程已经非常复杂了,这意味着传递了很多参数被检查为null,所以我无法真正应用我在这里找到的答案:T-SQL Stored Procedure - Dynamic AND/OR Operator

我还有其他办法吗?

2 个答案:

答案 0 :(得分:4)

操作员无法参数化。既然你提到这是一个存储过程,唯一的选择是在SP中编写T-SQL,并使用sp_executesql,即

//TODO : verify (whitelist) that @operator is in a known set of values...
// '=', '<>', '>', '<' etc - otherwise security risk
declare @sql varchar(4000) = 'select * from Foo where Bar '
          + @operator + ' @value'
exec sp_executesql @sql, N'@value int', @value

这会动态构建查询(@sql),但保持值(@value)在整个过程中参数化,因此我们只需要对运算符(@operator)进行白名单。

为了说明价值如何保持参数化,我们也可以使用:

//TODO : verify (whitelist) that @operator is in a known set of values...
// '=', '<>', '>', '<' etc - otherwise security risk
declare @sql varchar(4000) = 'select * from Foo where Bar '
          + @operator + ' @p'
exec sp_executesql @sql, N'@p int', @value

此处,@p内部 sql中参数的名称,@value存储过程中参数的名称; sp_executesql的第三/第四/第五/ etc参数映射到 second 参数中声明的参数sp_executesql(在此示例中,仅声明为@p })。

请注意,如果这不是存储过程,您可以在C#中执行查询构造步骤,再次将值保留为参数。

答案 1 :(得分:1)

我认为唯一的方法是使用动态sql,例如sq_executesql。这允许您将SQL语句创建为字符串,然后执行它。但它可能意味着重写现有的存储过程!