传递整个WHERE子句的SQL存储过程

时间:2010-06-21 14:56:54

标签: sql sql-server

我有一个

形式的SQL存储过程
SELECT [fields] FROM [table] WHERE @whereSql

我想传递一个参数(@whereSql)来指定整个WHERE子句,但是会返回以下错误:

An expression of non-boolean type specified in a context where a condition is expected

可以这样做吗?

5 个答案:

答案 0 :(得分:9)

简短的回答是你不能这样做 - SQL Server将变量的内容视为VALUE。它不会动态构建要执行的字符串(这就是为什么这是正确的方法来避免SQL注入攻击)。

你应该尽一切努力避免动态的WHERE,因为你正在努力,主要是出于这个原因,但也为了提高效率。相反,尝试构建WHERE子句,以便根据情况使具有大量OR的片段短路。

如果无法绕过它,你仍然可以从命令的各个部分构建一个自己组装的字符串,然后执行它。

所以你可以这样做:

DECLARE @mywhere VARCHAR(500)
DECLARE @mystmt VARCHAR(1000)
SET @mywhere = ' WHERE MfgPartNumber LIKE ''a%'' '
SELECT @mystmt = 'SELECT TOP 100 * FROM Products.Product AS p ' + @mywhere + ';'
EXEC( @mystmt )

但我建议您这样做:

SELECT TOP 100 * 
    FROM Products.Product AS p 
    WHERE 
        ( MfgPartNumber LIKE 'a%' AND ModeMfrPartNumStartsWith=1)
    OR  ( CategoryID = 123 AND ModeCategory=1 )

答案 1 :(得分:8)

我相信这可以使用Dynamic SQL完成。见下文:

CREATE PROCEDURE [dbo].[myProc]
@whereSql nvarchar(256)

AS
    EXEC('SELECT [fields] FROM [table] WHERE ' + @whereSql)
GO

也就是说,在实际使用它之前,你应该对动态SQL做一些认真的研究。 以下是我在快速搜索后遇到的一些链接:

答案 2 :(得分:3)

请务必完整阅读

www.sommarskog.se/dynamic_sql.html

答案 3 :(得分:1)

某些Answers中列出的动态SQL绝对是一种解决方案。但是,如果需要避免使用动态SQL,我更喜欢的解决方案之一是利用表变量(或临时表)来存储WHERE子句中用于比较的参数值。

以下是存储过程实现的示例。

CREATE PROCEDURE [dbo].[myStoredProc]
@parameter1 varchar(50)
AS

declare  @myTempTableVar Table(param1 varchar(50))
insert into @myTempTableVar values(@parameter1)

select * from MyTable where MyColumn in (select param1 from @myTempTableVar)

GO

如果要传递多个值,则逗号分隔值可以作为行存储在表变量中,并以相同的方式用于比较。

CREATE PROCEDURE [dbo].[myStoredProc]
@parameter1 varchar(50)
AS

--Code Block to Convert Comma Seperated Parameter into Values of a Temporary Table Variable
declare  @myTempTableVar Table(param1 varchar(50))
declare @index int =0, @tempString varchar(10)

if charindex(',',@parameter1) > 0
begin
 set @index = charindex(',',@parameter1)
 while @index > 0
  begin
    set @tempString = SubString(@parameter1,1,@index-1)
    insert into @myTempTableVar values (@tempString)
    set @parameter1 = SubString(@parameter1,@index+1,len(@parameter1)-@index)
    set @index = charindex(',',@parameter1)
  end

  set @tempString = @parameter1
  insert into @myTempTableVar values (@tempString)
end
else
insert into @myTempTableVar values (@parameter1)

select * from MyTable where MyColumn in (select param1 from @myTempTableVar)

GO

答案 4 :(得分:0)

http://sqlmag.com/t-sql/passing-multivalued-variables-stored-procedure

试试这个有效!!

CHARINDEX (',' + ColumnName + ',', ',' +
REPLACE(@Parameter, ' ', '') + ',') > 0

执行语法设置@参数=' nc1,nc2'