2016-04-25 108 views
3

我有一个存储过程来获得发票参数化WHERE子句中的SQL Server存储过程

的细节

一些场合,我通过只发送InvoiceID 但在其他一些场合取得发票的名单,我需要得到根据用户提供的搜索字段列出发票。为此,我将所有字段发送到存储过程,并使用以下参数。我只包括2列,但还有更多。

SELECT * FROM INVOICES I 
    WHERE 
    (@InvoiceNumber is null or I.InvoiceNumber = @InvoiceNumber) 
    and 
    (@PONo is null or I.PONo = @PONo) 

有没有办法将WHERE子句的条件作为一个参数发送?

+0

的解决方案是动态的SQL,但你最好的选择是缩小实际需要的搜索字段(答案“的所有领域都需要”是一个谎言。期。),并将其添加为参数。 – Paolo

回答

2

是的,它可以与动态SQL,但我非常不喜欢这样做。

SELECT * FROM tbl WHERE @condition

如果你正在考虑写的程序

CREATE PROCEDURE search_sp @condition varchar(8000) AS 
    SELECT * FROM tbl WHERE @condition 

就忘了。如果你这样做了,你还没有完成过渡到使用存储过程,并且你仍然在客户端中组装你的SQL代码。

它也会打开您的应用程序到SQL注入攻击。

0

(通过调用select compatibility_level, name from sys.databases,看到检查你的数据库是130或更高)那么你可以使用内建函数string_split

我发现它最像这样(摊开为清楚起见)

CREATE PROCEDURE [dbo].[GetInvoices] 
    @InvoiceNumber int = NULL 
    @PONo nvarchar(1024) = NULL 
AS 
SELECT * from [Invoices] AS [i] 
WHERE 
    i.InvoiceNumber = ISNULL(@InvoiceNunber, i.InvoiceNunber) 
    AND CASE 
     WHEN @PONo is null 
     THEN 1 
     ELSE (CASE 
      WHEN i.PONo IN (select value from string_split(@PONo, ',')) 
      THEN 1 
      ELSE 0 
      END) 
     END 
     = 1 

所以,如果你在一个空要么参数它被译为where x = x这始终是真正的传球,如果你传递一个CSV值,它从一个值的拆分表中选择它,如果存在,将导致where子句为where 1=1,如果该值不在输入列表中,则为true或0=1

因此,您可以在此处输入发票编号或采购订单编号,或两者兼得,或者两者均不相同,并且它应返回您的期望值。