0

是否可以在 T-SQL 中编写LIKE条件以匹配包含通配符的逗号分隔列表到字符串。让我用一个例子进一步解释:

假设您在字段中有以下命令分隔的 url 列表:

'/, /news/%, /about/'

现在这里有一些我想与上面的字符串匹配的字符串示例:

  1. '/'
  2. '/消息/'
  3. '/新闻/2/'
  4. '/关于/'

这是一些不匹配的字符串:

  1. '/接触/'
  2. '/关于我/'

我过去通过编写一个拆分函数然后对每个函数做一个类似的操作来实现这一点。但是,我试图让我的查询在不支持函数的 SQL Server CE 中工作。

如果您想知道我是如何使用 split 函数实现它的:

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

如果有人可以提供帮助,我将不胜感激。谢谢

4

2 回答 2

2

我可以想到几个选择:

  1. 使用会话键控表:删除与当前 spid 匹配的行,使用当前 spid 插入所需的行,从 SP 中的表中读取,从表中删除(再次)。

  2. 让您的客户提交包含许多 OR ... LIKE ... 子句的查询。

  3. 编写一个与您的函数执行相同操作并返回记录集的 SP。INSERT YourTable EXEC SP @Strings你就完成了!

  4. 在拆分字符串的派生表方法中使用 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 的关于拆分字符串的博客文章

此外,任何认真的 SQL Server 数据库学生都应该阅读 Erland Sommarskog 的如何在存储过程之间共享数据

于 2012-07-29T07:24:00.770 回答
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 和模式填充另一个表来加入。

于 2012-07-29T07:08:28.497 回答