Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
传递整个WHERE子句的SQL存储过程_Sql_Sql Server - Fatal编程技术网

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

传递整个WHERE子句的SQL存储过程,sql,sql-server,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 这可以做到吗?简单的回答是不能这样做——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

这可以做到吗?

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

你应该尽一切努力避免动态,因为你正试图这样做,主要是因为这个原因,但也是为了效率。相反,尝试建立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 )

我相信这可以通过使用动态SQL来实现。见下文:

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

AS
    EXEC('SELECT [fields] FROM [table] WHERE ' + @whereSql)
GO
也就是说,在实际使用动态SQL之前,应该对其进行一些认真的研究。 以下是我在快速搜索后发现的几个链接:


请确保您已充分阅读此内容

试试这个,它很管用

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

执行语法集@Parameter='nc1,nc2'

一些答案中列出的动态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

你为什么要这么做?你最终会以所有的代价而得不到存储过程的好处,我认为这不是存储过程的好用途。Amir给了你一个可能性,但在你的例子中,我想我会使用视图。Joel和Jeff在Podcast 31中讨论SQL参数化。删除我的答案,给你一个+1。这是我在帖子中的链接:绝妙的答案-我也在走动态SQL的路线(从我为Access后端编写脏VBA的日子开始),但这向我展示了一个更安全的选择,只是思想上的一个转变。使用大量的ORs短路不会弄乱查询优化器吗?