是否可以在T-SQL中编写LIKE
条件,以匹配包含通配符到字符串的逗号分隔列表。让我用一个例子进一步解释:
假设您在字段中有以下命令分隔的网址列表:
'/, /news/%, /about/'
现在,这里有一些字符串示例,我想与上面的字符串匹配:
这里有一些不匹配的字符串:
我过去通过编写分割函数然后在每个函数上做了类似的事情来实现这一点。但是,我试图让我的查询在不支持函数的SQL Server CE中工作。
如果您想知道我是如何使用拆分功能实现的:
SELECT Widgets.Id
FROM Widgets
WHERE (SELECT COUNT(*) FROM [dbo].[Split](Urls, ',') WHERE @Input LIKE Data) > 0
以下是拆分功能:
CREATE FUNCTION [dbo].[Split]
(
@RowData NVARCHAR(MAX),
@Separator NVARCHAR(MAX)
)
RETURNS @RtnValue TABLE
(
[Id] INT IDENTITY(1,1),
[Data] NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Separator, @RowData)
WHILE (@FoundIndex > 0)
BEGIN
INSERT INTO @RtnValue ([Data])
SELECT Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowData = SUBSTRING(@RowData, @FoundIndex + DATALENGTH(@Separator) / 2, LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Separator, @RowData)
END
INSERT INTO @RtnValue ([Data])
SELECT Data = LTRIM(RTRIM(@RowData))
RETURN
END
如果有人可以提供帮助,我会很感激。感谢
答案 0 :(得分:2)
我可以想到几个选项:
使用会话密钥表:删除与当前spid匹配的行,使用当前spid插入所需的行,从SP中的表中读取,从表中删除(再次)。
让您的客户提交一个包含许多OR ... LIKE ...子句的查询。
编写一个与您的函数完全相同的SP并返回一个记录集。 INSERT YourTable EXEC SP @Strings
已经完成了!
在分割字符串的派生表方法中使用numbers-table-charindex-into-string。
示例强>
让我以一个结合思想#3和#4的例子为你充实。当然,您的功能代码也可以调整。
构建单独的Numbers
表。这是示例创建脚本:
--Numbers Table with 8192 elements (keeping it small for CE)
CREATE TABLE Numbers (
N smallint NOT NULL CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED
);
INSERT Numbers VALUES (1);
WHILE @@RowCount < 4096
INSERT Numbers SELECT N + (SELECT Max(N) FROM Numbers) FROM Numbers;
SP:
CREATE PROCEDURE dbo.StringSplitRowset
@String varchar(8000)
AS
SELECT Substring(@String, l.StartPos, l.Chars) Item
FROM (
SELECT
S.StartPos,
IsNull(NullIf(CharIndex(',', @String, S.StartPos), 0) - S.StartPos, 8000)
FROM (
SELECT 1 UNION ALL
SELECT N.N + 1 FROM Numbers N WHERE Substring(@String, N.N, 1) = ','
) S (StartPos)
) L (StartPos, Chars);
用法,很容易就像馅饼一样:
DECLARE @String varchar(8000);
SET @String = 'abc,def,ghi,jkl';
CREATE TABLE #Split (S varchar(8000));
INSERT #Split EXEC dbo.StringSplitRowset @String;
SELECT * FROM #Split;
结果:
abc
def
ghi
jkl
最后,如果您不想构建数字表,则可以使用此SP。我想你会发现这两个SP中的一个对你来说效果很好。还有其他字符串拆分实现也可以。
ALTER PROCEDURE dbo.StringSplitRowset
@String varchar(8000)
AS
SELECT Substring(@String, l.StartPos, l.Chars) Item
FROM (
SELECT
S.StartPos,
IsNull(NullIf(CharIndex(',', @String, S.StartPos), 0) - S.StartPos, 8000)
FROM (
SELECT 1 UNION ALL
SELECT N.N + 1
FROM (
SELECT A.A * 4096 + B.B * 1024 + C.C * 256 + D.D * 64 + E.E * 16 + F.F * 4 + G.G N
FROM
(SELECT 0 UNION ALL SELECT 1) A (A),
(SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) G (G),
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) F (F),
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) E (E),
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) D (D),
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) C (C),
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) B (B)
) N (N)
WHERE Substring(@String, N.N, 1) = ','
) S (StartPos)
) L (StartPos, Chars)
任何认真理解分解字符串不同方式的性能影响的SQL编写者都应该看Aaron Bertrand's blog post on splitting strings。
此外,任何严肃的SQL Server数据库学生都应该看到Erland Sommarskog's How to Share Data between Stored Procedures。
答案 1 :(得分:0)
SQL Server CE是否允许您使用XML功能进行拆分并使用CROSS APPLY?如果是这样,你可以这样做:
SELECT DISTINCT T1.id
FROM (
SELECT id, CAST(('<X>'+
REPLACE(REPLACE(urls,' ',''),',','</X><X>')+
'</X>'
) AS xml
) as URLsXML
FROM dbo.Widgets
) AS T1
CROSS APPLY(
SELECT N.value('.', 'varchar(50)') AS URLPattern
FROM URLsXML.nodes('X') AS S(N)
) AS T2
WHERE @Input LIKE T2.URLPattern
更新:我刚检查过。看起来SQL Server CE不支持XML数据类型或CROSS APPLY。 我认为你将不得不填充另一个带有ID和模式的表来加入。