小编典典

将定界字符串传递给存储过程以搜索数据库

sql

如何将以空格或逗号分隔的字符串传递给存储过程和过滤结果?我正在尝试做类似的事情-

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

然后是我要首先存储的过程

  1. 查找所有具有名字或姓氏的记录,例如key1
  2. 使用名字或姓氏(例如key2)过滤步骤1
  3. 使用名字或姓氏(如键3)过滤步骤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开发人员”返回2行

  2. “ xyz abc”返回1行

  3. “ abc开发者”返回1行

  4. “ hello”返回2行

  5. “ hello开发人员”返回2行

  6. “ xyz”返回2行


阅读 219

收藏
2021-03-23

共1个答案

小编典典

由于您不能使用表参数(在SQL Server 2008上不是),请尝试传递CSV字符串并让存储过程为您将其拆分为行。

在SQL Server中有很多分割字符串的方法。本文介绍了几乎每种方法的优点和缺点:

Erland Sommarskog撰写的“当表值参数无法剪切时,SQL Server
2005及更高版本中的数组和列表”

您需要创建一个拆分功能。这是分割函数的使用方式:

SELECT
    *
    FROM YourTable                               y
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value

我更喜欢使用数字表方法在TSQL中拆分字符串,但是在SQL Server中拆分字符串的方法有很多,请参见前面的链接,其中解释了每种方法的优点和缺点。

为了使Numbers Table方法起作用,您需要进行一次时间表设置,这将创建一个Numbers包含1至10,000行的表:

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

现在,您可以轻松地将以空格分隔的字符串拆分成一个表,然后在表上进行连接或使用,但是您需要使用此代码。这些代码基于OP最新的问题编辑:

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)
2021-03-23