2009-10-13 55 views
0

我有SQL Server 2008中的一個數據庫表,具有5個nvarchar(max)列。我們使用CONTAINS函數在這些列中查找文本。SQL Server動態列表中包含函數

我們可以看看在使用這種查詢的所有五列:

SELECT * 
FROM SomeTable ST 
WHERE CONTAINS((ST.ColumnA, ST.ColumnB, ST.ColumnC, ST.ColumnD, ST.ColumnE) , '"Strawberry"') 

現在,我們要搜索文本的一個或多個動態這些列。例如,只能查看ColumnB和ColumnE。我嘗試使用CASE語句,但是我不能。

我能想到的唯一解決方案是動態SQL,但我寧願避免這種情況。 (完整的查詢非常複雜。)有沒有辦法在不使用動態SQL的情況下執行此操作?

回答

0

我只能想到這樣的解決方案,但這並不使用全文搜索...讓我知道它是否對你有用。

SELECT * 
FROM SomeTable ST 
WHERE 1=1 
AND ((@colA = '') OR ST.ColumnA LIKE @colA) 
AND ((@colB = '') OR ST.ColumnB LIKE @colB) 
AND ((@colC = '') OR ST.ColumnC LIKE @colC) 
AND ((@colD = '') OR ST.ColumnD LIKE @colD) 
AND ((@colE = '') OR ST.ColumnE LIKE @colE) 

search_on參數應該是位(0,1),因此,當設置爲1時,該列上的搜索將被激活。

+0

不使用含有做全文搜索。 – HLGEM 2009-10-13 21:51:18

+0

如果您認爲SQL將使邏輯更加快捷,您是不是會使用'和'子句或'or',因此第一個子句爲false會創建快捷方式? – Andrew 2009-10-13 21:56:02

+0

圓括號內的OR會告訴SQL,如果第一個參數爲空,則不要檢查第二個條件,對於每個「AND」行,依此類推 – 2009-10-13 21:59:26

1

我能想到的避免使用動態SQL的唯一方法是使用臨時表,if語句和存儲過程。爲包含要搜索該列的文本的每個列使用參數存儲過程。創建一個臨時表或表變量來存儲臨時結果。

對每個可能的列有五個不同的if語句。如果變量不爲null,則在每個if中插入臨時表。例如:

IF @ColA is not null 
BEGIN 
INSERT INTO #temp 
SELECT * FROM SomeTable ST 
     WHERE CONTAINS((ST.ColumnA) , @ColA) 
END 

最後從臨時表中選擇以顯示您的結果。

只有當你沒有很多列並且不太可能會添加更多時,這種方法纔會有效。坦率地說,你有多個列需要對同一個搜索字符串進行全文搜索這一事實表明你可能在數據庫設計方面有一個基本問題。

0

你可以聯合5個人的情況下,然後PIVOT和連接。我不確定它比動態SQL更好。

你最終會得到這樣的:

SET @FindKey = '%B%E%' -- This is your search which field criteria 

WITH RESULTS1 AS (
    SELECT PK, 'A' AS Col 
    FROM SomeTable ST 
    WHERE @FindKey LIKE '%A%' AND CONTAINS(ST.ColumnA, '"Strawberry"') 
    UNION 
    SELECT PK, 'B' AS Col 
    FROM SomeTable ST 
    WHERE @FindKey LIKE '%B%' AND CONTAINS(ST.ColumnB, '"Strawberry"') 
    UNION 
    SELECT PK, 'C' AS Col 
    FROM SomeTable ST 
    WHERE @FindKey LIKE '%C%' AND CONTAINS(ST.ColumnC, '"Strawberry"') 
    UNION 
    SELECT PK, 'D' AS Col 
    FROM SomeTable ST 
    WHERE @FindKey LIKE '%D%' AND CONTAINS(ST.ColumnD, '"Strawberry"') 
    UNION 
    SELECT PK, 'E' AS Col 
    FROM SomeTable ST 
    WHERE @FindKey LIKE '%E%' AND CONTAINS(ST.ColumnE, '"Strawberry"') 
) 
,RESULTS2 AS (
SELECT PK, ISNULL([A], '') + ISNULL([B], '') + ISNULL([C], '') + ISNULL([D], '') + ISNULL([E], '') AS FoundKey 
FROM RESULTS PIVOT (MIN(Col) FOR Col IN ([A], [B], [C], [D], [E])) AS pvt 
) 
SELECT * 
FROM SomeTable 
INNER JOIN RESULTS2 
    ON RESULTS2.PK = SomeTable.PK 
WHERE RESULTS2.FoundKey LIKE @FindKey 
+0

我沒有想過數據透視表,但我認爲這會對布爾搜索有問題。如果你搜索「草莓和香蕉」,它將只能找到那些在單個欄目中都有單詞的人。如果「草莓」在ColumnA中,而「Bananas」在ColumnB中,則它不會返回記錄。 這是正確的嗎? – 2009-10-14 12:43:32

+0

是的,這是正確的,要做這樣的事情,你必須將該邏輯擴展到UNION中。 我真的認爲動態SQl是一個很好的選擇。 – 2009-10-14 15:36:11