简体   繁体   English

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

[英]Passing SQL stored procedure entirety of WHERE clause

I have a SQL stored procedure of the form 我有一个形式的SQL存储过程

SELECT [fields] FROM [table] WHERE @whereSql

I want to pass the procedure an argument (@whereSql) which specifies the entire WHERE clause, but the following error is returned: 我想向过程传递一个参数(@whereSql),该参数指定整个WHERE子句,但返回以下错误:

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

Can this be done? 能做到吗?

The short answer is that you can't do it like this -- SQL Server looks at the contents of a variable as a VALUE. 简短的答案是您不能这样做-SQL Server将变量的内容视为VALUE。 It doesn't dynamically build up the string to execute (which is why this is the correct way to avoid SQL injection attacks). 它不会动态构建要执行的字符串(这就是为什么这是避免SQL注入攻击的正确方法)的原因。

You should make every effort to avoid a dynamic WHERE as you're trying to do, largely for this reason, but also for the sake of efficiency. 您应该尽一切努力避免动态的WHERE,主要是因为这个原因,也是为了提高效率。 Instead, try to build up the WHERE clause so that it short-circuits pieces with lots of ORs, depending on the situation. 相反,请尝试建立WHERE子句,以便根据情况使具有很多OR的块短路。

If there's no way around it, you can still build a string of your own assembled from the pieces of the command, and then EXEC it. 如果没有办法解决,您仍然可以根据命令片段构建自己组装的字符串,然后执行它。

So you could do this: 因此,您可以这样做:

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 )

But I recommend instead that you do this: 但我建议您这样做:

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

I believe this can be done using Dynamic SQL. 我相信可以使用动态SQL来完成。 See below: 见下文:

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

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

That said, you should do some serious research on dynamic SQL before you actually use it. 也就是说,在实际使用动态SQL之前,应该对其进行认真的研究。 Here are a few links that I came across after a quick search: 快速搜索后,我遇到了一些链接:

Make sure you read this fully 确保您已阅读完整

www.sommarskog.se/dynamic_sql.html www.sommarskog.se/dynamic_sql.html

Dynamic SQL listed in some of the Answers is definitely a solution. 某些“答案”中列出的动态SQL绝对是一种解决方案。 However, if Dynamic SQL needs to be avoided, one of the solutions that I prefer is to make use of table variables (or temp tables) to store the parameter value that is used for comparison in WHERE clause. 但是,如果需要避免使用动态SQL,我更喜欢的解决方案之一是利用表变量(或临时表)在WHERE子句中存储用于比较的参数值。

Here is an example Stored Procedure implementation. 这是存储过程实现的示例。

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

In case you want to pass in multiple values, then the comma separated values can be stored as rows in the table variable and used in the same way for comparison. 如果要传递多个值,则可以将逗号分隔的值存储为表变量中的行,并以相同的方式用于比较。

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

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

try this it works!! 试试这个,它的工作原理!

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

execute syntax set @Parameter= 'nc1,nc2' 执行语法设置@ Parameter ='nc1,nc2'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM