簡體   English   中英

SQL Server存儲過程中的參數化WHERE子句

[英]Parameterized WHERE clause in SQL Server Stored Procedure

我有一個存儲過程來獲取發票的詳細信息

有些情況下,我只通過發送InvoiceID獲得發票清單。但在其他一些場合,我需要根據用戶提供的搜索字段獲取發票清單。 為此,我將所有字段發送到存儲過程並使用以下參數。 我只包括2列,但還有更多。

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

有沒有辦法將WHERE子句的條件作為一個參數發送?

是的,可以使用Dynamic SQL,但我非常不鼓勵這樣做。

SELECT * FROM tbl WHERE @condition

如果您正在考慮編寫該程序

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

把它忘了吧。 如果您這樣做,您還沒有完成使用存儲過程的轉換,並且您仍然在客戶端中組裝SQL代碼。

它還將打開您的SQL注入攻擊應用程序。

您可以使用自定義類型將表作為參數https://msdn.microsoft.com/pl-pl/library/bb510489(v=sql.110).aspx傳遞,或者您可以使用默認參數

如果您正在使用SQL Server 2016或類似的(通過調用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

因此,如果將null傳遞給任一參數,則將其轉換為where x = x ,其始終為true,如果傳入CSV值,則會從值的拆分表中選擇它,如果存在,則會導致子句是where 1=1 ,如果輸入列表中不存在該值,則為0=10=1

因此,您可以在此處傳遞發票編號或采購訂單編號,或兩者兼而有之,或者既不會返回您期望的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM