代码之家  ›  专栏  ›  技术社区  ›  rs.

向存储过程传递分隔字符串以搜索数据库

  •  2
  • rs.  · 技术社区  · 16 年前

    如何将空格或逗号分隔的字符串传递给存储过程和筛选结果? 我试着做一些像-

    Parameter      Value
    --------------------------
    @keywords      key1 key2 key3
    

    1. 查找包含第一个或最后一个的所有记录 像key1这样的名称
    2. 用first或last筛选步骤1 名称如键2

    另一个例子:

    col1    |       col2        | col3
    ------------------------------------------------------------------------
    hello xyz   |   abc is my last name | and i'm a developer
    hello xyz   |       null        | and i'm a developer
    

    如果我搜索任何以下内容,它应该返回每个?

    1. “xyz abc”返回1行

    2. “abc developer”返回1行

    3. “hello”返回2行

    4. “hello developer”返回2行

    5. “xyz”返回2行

    2 回复  |  直到 16 年前
        1
  •  2
  •   KM.    16 年前

    由于不能使用表参数(在SQLServer2008上不可用),请尝试传入CSV字符串,并让存储过程将其拆分为行。

    "Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog

    你需要创建一个分割函数。这就是拆分函数的用法:

    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 但是在SQLServer中有很多方法可以分割字符串,请参阅前面的链接,其中解释了每种方法的优缺点。

    要使Numbers表方法工作,您需要执行一次性表设置,这将创建一个表 Numbers 包含从1到10000行的:

    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)
    

    设置完数字表后,创建此拆分函数:

    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 
    

    CREATE TABLE YourTable (PK int, col1 varchar(20), col2 varchar(20), col3 varchar(20))
    --data from question
    INSERT INTO YourTable VALUES (1,'hello xyz','abc is my last name','and i''m a developer')
    INSERT INTO YourTable VALUES (2,'hello xyz',null,'and i''m a developer')
    
    CREATE PROCEDURE YourProcedure
    (
        @keywords   varchar(1000)
    )
    AS
    
    SELECT
        @keywords AS KeyWords,y.* 
        FROM (SELECT
                  t.PK
                  FROM dbo.FN_ListToTable(' ',@keywords) dt
                      INNER JOIN YourTable             t ON  t.col1 LIKE '%'+dt.ListValue+'%' OR t.col2 LIKE '%'+dt.ListValue+'%' OR t.col3 LIKE '%'+dt.ListValue+'%'
                  GROUP BY t.PK
                  HAVING COUNT(t.PK)=(SELECT COUNT(*) AS CountOf FROM dbo.FN_ListToTable(' ',@keywords))
             ) dt
            INNER JOIN YourTable y ON dt.PK=y.PK
    GO
    
    --from question   
    EXEC YourProcedure 'xyz developer'-- returns 2 rows
    EXEC YourProcedure 'xyz abc'-- returns 1 row
    EXEC YourProcedure 'abc developer'-- returns 1 row
    EXEC YourProcedure 'hello'--  returns 2 rows
    EXEC YourProcedure 'hello developer'--  returns 2 rows
    EXEC YourProcedure 'xyz'-- returns 2 rows
    

    输出:

    KeyWords       PK    col1       col2                 col3
    -------------- ----- ---------- -------------------- --------------------
    xyz developer  1     hello xyz  abc is my last name  and i'm a developer
    xyz developer  2     hello xyz  NULL                 and i'm a developer
    
    (2 row(s) affected)
    
    KeyWords       PK    col1       col2                 col3
    -------------- ----- ---------- -------------------- --------------------
    xyz abc        1     hello xyz  abc is my last name  and i'm a developer
    
    (1 row(s) affected)
    
    KeyWords       PK    col1       col2                 col3
    -------------- ----- ---------- -------------------- --------------------
    abc developer  1     hello xyz  abc is my last name  and i'm a developer
    
    (1 row(s) affected)
    
    KeyWords       PK    col1       col2                 col3
    -------------- ----- ---------- -------------------- --------------------
    hello          1     hello xyz  abc is my last name  and i'm a developer
    hello          2     hello xyz  NULL                 and i'm a developer
    
    (2 row(s) affected)
    
    KeyWords        PK    col1       col2                 col3
    --------------- ----- ---------- -------------------- --------------------
    hello developer 1     hello xyz  abc is my last name  and i'm a developer
    hello developer 2     hello xyz  NULL                 and i'm a developer
    
    (2 row(s) affected)
    
    KeyWords       PK    col1       col2                 col3
    -------------- ----- ---------- -------------------- --------------------
    xyz            1     hello xyz  abc is my last name  and i'm a developer
    xyz            2     hello xyz  NULL                 and i'm a developer
    
    (2 row(s) affected)
    
        2
  •  1
  •   joelt    16 年前

    select firstname, lastname from @test t1
    inner join persondata t on t.firstname like '%' + t1.x + '%' or t.lastname like '%' + t1.x + '%'
    group by firstname, lastname
    having count(distinct x) = (select count(*) from @test)