2016-04-25 149 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

因此,您可以在此處輸入發票編號或採購訂單編號,或兩者兼得,或者兩者均不相同,並且它應返回您的期望值。