2009-02-10 113 views
1

我有一個Visual Basic .NET應用程序的搜索屏幕具有文本框:多參數搜索2000

  1. 名VARCHAR(50)
  2. 姓VARCHAR(50)
  3. 中間名VARCHAR(50)
  4. DOB的DateTime
  5. 家庭電話VARCHAR(10)
  6. 工作電話VARCHAR(10)

我將如何在SQL Server 2000中創建一個存儲過程,使我能夠在所有/某些/某個字段上進行搜索。如果用戶只輸入姓名和家庭電話號碼的數據,那麼對於沒有輸入數據的其餘參數,我需要做什麼。我嘗試了下面的select語句,但它不能正常工作。

Select Last_Name, First_Name, Mid_Name, DOB, Home_Phone, Work_Phone from dbo.tblClient 
Where Last_Name Like '%@LastName' and 
    First_Name Like '%@FirstName' and 
    Mid_Name Like '%@MiddleName' and 
    DOB Like '%DOB' and 
    Home_Phone Like '%@HomePhone' and 
    Work_Phone Like '%@WorkPhone' 

回答

3

我使用這個模式很多:

Select Last_Name, First_Name, Mid_Name, DOB, Home_Phone, Work_Phone from dbo.tblClient 
Where (@LastName is null or Last_Name Like '%'+ @LastName) 
and (@FirstName is null or First_Name Like '%'+ @FirstName) 
and (@HomePhone is null or Home_Phone Like '%'+ @HomePhone) 
-- etc... 

它會忽略這不是提供,同時還提供良好的性能什麼。更好的是,它不會訴諸動態SQL來實現它。

0

快速的方法來做到這一點會是這樣的

凡(姓氏LIKE @LastName + '%' 或@LastName IS NULL)和 (如同將First_Name + @firstName '%' OR @名字IS NULL)和 等等

厄蘭Sommarskog有不同的方法來做到這一點,一些偉大的文章其性能影響here

+0

您可能想要翻轉您的ORs的順序,或者在測試存在之前最終執行查找。充其量只會是狗慢。更可能的是,它會簡單地拋出。 – 2009-02-10 22:45:34

+0

@Jason:對於@LastName爲null表達式變爲(Last_Name爲Null或Null Is Null),重新排序OR操作數(甚至假定SQL 2000的捷徑)幾乎是不可能的(忽略語法錯誤)會有所作爲。 – AnthonyWJones 2009-02-10 22:54:58

+0

我不認爲SQL真的讓我們決定在這種情況下的評估順序。由於評估變量的成本非常小,因此優化程序會在決定是否將其與列進行比較之前自行評估(將其視爲常量)。 – KenJ 2009-02-10 22:55:48

0

在你的存儲過程或你的VB中,你將不得不決定你如何處理沒有輸入。例如我使用:

IF ltrim(rtrim(@FirstName)) = '' 
SET @FirstName = null 

...在我的存儲過程中。你可能不得不嘗試ORs而不是ANDs。你基本上告訴你的查詢,你必須通過使用AND來滿足所有這些條件,而不管沒有任何輸入。

0

快速骯髒的解決方案。

Select Last_Name, First_Name, Mid_Name, DOB, Home_Phone, Work_Phone from dbo.tblClient 
Where (Last_Name Like '%' + @LastName OR @LastName Is Null) and 
(First_Name Like '%' + @FirstName OR @FirstName Is Null) and 
(Mid_Name Like '%' + @MiddleName OR @MiddleName Is Null) and 
(DOB Like '%' + @DOB OR @DOB Is Null) and 
(Home_Phone Like '%' + @HomePhone OR @HomePhone Is Null and 
(Work_Phone Like '%' + @WorkPhone OR @WorkPhone Is Null) 

注意我更正了參數的用法。你是不是還想在參數的另一端使用通配符?你也會真的使用Like to a Date of Birth字段嗎?

這是不會在一張大桌子上表現很好。一個更高性能的解決方案是隻用Where子句中的必需字段來構造SQL。

0

只是爲了澄清爲什麼你原來的SQL不起作用;

您需要將%通配符連接到參數值,但您寫的是創建一個包含通配符和參數名稱的文字字符串,例如

Work_Phone Like '%@WorkPhone'

應該寫成

Work_Phone Like '%' + @WorkPhone

你擁有的SQL應,如果你正在返回的沒有一個值輸入的參數爲空字符串工作(即你正在返回「」,而不是NULL) - 這些字段的Like比較將只包含%通配符(即匹配任何值)。但是,這並不是非常有效,因爲理想情況下,您只需要在用戶輸入值的字段上進行比較。這可能需要一些動態生成的SQL,如kenj鏈接到的文章所示。

如果你的tblClient表雖然不是那麼大,那麼你所做的就可能就足夠了。

0

如何使用ISNULL()函數確定是否已將值傳遞到存儲過程,如果不是,則在每種情況下將WHERE子句字段值設置爲等於自身(,如果有人能夠想到更好的選擇詞來描述這一點,我會更新答案)。

SELECT 
    Last_Name, 
    First_Name, 
    Mid_Name, 
    DOB, 
    Home_Phone, 
    Work_Phone 
FROM 
    dbo.tblClient 
WHERE 
    Last_Name LIKE '%' + ISNULL(@LastName, Last_Name) AND 
    First_Name LIKE '%' + ISNULL(@FirstName, First_Name) AND 
    Mid_Name LIKE '%' ISNULL(@MiddleName, Mid_Name) AND 
    DOB LIKE '%' + ISNULL(@DOB, DOB) AND 
    Home_Phone LIKE '%' + ISNULL(@HomePhone, Home_Phone) AND 
    Work_Phone LIKE '%' + ISNULL(@WorkPhone, Work_Phone) 

您還可以爲每個存儲過程參數設置NULL默認值。