這是一個非常複雜的話題,具有許多微妙的性能影響。你真的需要通過厄蘭Sommarskog閱讀這些優秀的文章:
Dynamic Search Conditions in T-SQL
The Curse and Blessings of Dynamic SQL
既然沒有「一刀切」這種查詢方法,也有細微的性能影響你該怎麼辦這個。如果您想超越只是讓查詢返回正確的答案,不管它有多慢,看看這篇文章:Dynamic Search Conditions in T-SQL by Erland Sommarskog。它涵蓋了每種方法,並且非常詳細地給出了每種方法的PRO和Cons。
如果您可以確定搜索列的最小和最大可能範圍,並且搜索列不是NULL,那麼您可以比(@Search IS NULL或Col = @ Search),see this area of the above linked article做得更好。不過,你應該閱讀整篇文章,有很多變化取決於你的情況,你真的需要學習多種方法以及何時使用它們。
如果您想在單個字符串參數中搜索多個術語,則需要拆分該字符串。
您需要創建一個拆分功能。這是一個分裂的功能如何使用:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
I prefer the number table approach to split a string in TSQL但也有許多方法來拆分在SQL Server中的字符串,見前面的鏈接,這說明各的優點和缺點。
對於數字表的方法來工作,你需要做的這一次表的設置,這將創建一個包含從1到10000行的表Numbers
:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
一旦Numbers表格設置,創建此分割功能:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
@SplitOn char(1) --REQUIRED, the character to split the @List string on
,@List varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN
(
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = @SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
);
GO
您現在可以輕鬆地拆分CSV字符串轉換成表格,並加入就可以了:
select * from dbo.FN_ListToTable(',','1,2,3,,,4,5,6777,,,')
OUTPUT:
ListValue
-----------------------
1
2
3
4
5
6777
(6 row(s) affected)
您可以使用多個搜索標準字符串是這樣的:
DECLARE @Persons table (FirstName varchar(50) , LastName varchar(50), EmailAddress varchar(200))
INSERT INTO @Persons VALUES ('aaa','bbb','[email protected]')
INSERT INTO @Persons VALUES ('xxx','yyy','[email protected]')
INSERT INTO @Persons VALUES ('aaa','yyy','[email protected]')
INSERT INTO @Persons VALUES ('111','222','[email protected]')
declare @searchTerm varchar(50)
set @searchTerm = 'aaa bbb'
--this should use an index on FirstName and LastName if they exist, no index usage on EmailAddress
select
p.* --<<"*" isn't good, only list the columns you need
FROM @Persons p
INNER JOIN dbo.FN_ListToTable(' ',@searchTerm) b on p.FirstName=b.Listvalue
UNION
select
p.* --<<"*" isn't good, only list the columns you need
FROM @Persons p
INNER JOIN dbo.FN_ListToTable(' ',@searchTerm) b on p.LastName=b.Listvalue
UNION
select
p.* --<<"*" isn't good, only list the columns you need
FROM @Persons p
INNER JOIN dbo.FN_ListToTable(' ',@searchTerm) b on p.EmailAddress like '%'+b.Listvalue+'%'
OUTPUT:
FirstName LastName EmailAddress
---------- ---------- -------------------------
aaa bbb [email protected]
aaa yyy [email protected]
xxx yyy [email protected]
(3 row(s) affected)
這種方法適用於任何數量的參數工作:
aaa
aaa
aaa bbb
aaa bbb
aaa bbb eee
aaa bbb eee ddd
aaa bbb eee