2014-03-27 49 views
1

我需要編寫一個搜索查詢(存儲過程),其中輸入參數的數量將大於15.用戶可以傳遞單個參數值或參數組合。搜索查詢動態與靜態 - SQL Server 2012

什麼是最好的辦法

  1. 靜態如下方法:

    DECLARE @FirstName VARCHAR(50) = 'XYZ' , 
    @LastName VARCHAR(50) = 'ABC' , 
    @MiddleName VARCHAR(50) = '999-9999%''; Select 1 as Abc where 1 like ''%1' 
    SELECT * 
    FROM [Person].[Person] 
    WHERE FirstName LIKE '%' + @FirstName + '%' 
        OR LastName LIKE '%' + @LastName + '%' 
        OR MiddleName LIKE '%' + @MiddleName + '%' 
    
  2. 動態SQL方法如下:

    DECLARE @FirstName VARCHAR(50) = 'XYZ', @LastName VARCHAR(50) = 'ABC', @MiddleName VARCHAR(50) = '999-9999%' 
    
    DECLARE @select VARCHAR(5000) = 'Select * from [Person].[Person] ' 
    DECLARE @WhereClause VARCHAR(5000) = 'Where' 
    IF (@FirstName IS NOT NULL OR @FirstName <> '') 
        SET @WhereClause = @WhereClause + ' FirstName Like ''%' + @FirstName + '%''' 
    
    IF (@LastName IS NOT NULL OR @LastName<> '') 
        IF (@WhereClause <> 'Where') 
         SET @WhereClause = @WhereClause + ' OR LastName Like ''%' + @LastName+ '%''' 
        ELSE 
         SET @WhereClause = @WhereClause + ' LastName Like ''%' + @LastName+ '%''' 
    
    IF (@MiddleName IS NOT NULL OR @MiddleName <> '') 
        IF (@WhereClause <> 'Where') 
         SET @WhereClause = @WhereClause + ' OR MiddleName Like ''%' + @MiddleName + '%''' 
        ELSE 
         SET @WhereClause = @WhereClause + ' MiddleNameLike ''%' + @MiddleName + '%''' 
    

    EXEC(@select + @WhereClause )

的問題吧:

隨着接近1我必須包括WHERE子句中的每一個參數。我認爲,即使參數的值沒有提供,它仍然會在相關列中搜索,但性能會降低,並且每次都會有所降低。

與方法2我認爲它很可能SQL注入。 實施例: 如果在殼體2中的參數值作爲

DECLARE @FirstName VARCHAR(50) = 'XYZ', @LastName VARCHAR(50) = 'ABC', @MiddleName VARCHAR(50) = '999-9999%''; Select 1 as Abc where 1 like ''%1'; 

傳遞所得到的SQL查詢將執行將是

Select * from [Person].[Person] Where FirstName Like '%XYZ%' OR LastName Like '%ABC%' OR MiddleName Like '%999-9999%'; Select 1 as Abc where 1 like '%1%' 

這是不好的。

那麼什麼是最好的方式來編碼與最佳性能。

回答

1

我更喜歡方法#1。

  • 更容易保持在#1中的代碼。
  • 在大多數情況下#1將比#2更快
  • 處理報價裏面的報價是頭痛的。 ' OR LastName Like ''%' + @LastName+ '%'''
  • 動態sql很難調試。可能不會在這種情況下。
  • 當您的要求更改時,您的動態代碼將變得更加混亂,並且 更加混亂。
  • 查詢計劃不會被緩存在#2中。
  • SQL注入如您所示。
0

動態SQL通常會導致性能下降,因爲它無法在SQL Server中緩存查詢計劃。

我個人更喜歡方法1,但如果沒有正確完成,它可能會非常慢,特別是因爲開放式LIKE語句(如var LIKE「%text%」)可能需要大量時間才能執行。

我的建議是有輸入參數有空默認值,然後構建您的WHERE子句如下

SELECT * 
FROM table t 
WHERE t.column1 = ISNULL(@param1, t.column1) 
AND t.column2 = ISNULL(@param2, t.column2) 

這意味着,在不設置該參數的情況下它只是返回所有其他匹配結果。

您可能必須通過但使用的最小和最大可能的日期/時間,其中的參數爲NULL,以確保所有記錄應該是在範圍內做一些聰明的日期範圍匹配。

+0

避免使用't.column1 = ISNULL(@ param1,t.column1)'如果't.column1'爲'NULL',那麼即使您在't.column2'上找到匹配項,您也會省略那一排。對於這種情況,我認爲將'AND'改爲'OR'可能奏效。 –