sql >> Databáze >  >> RDS >> Sqlserver

Předání odděleného řetězce do uložené procedury k prohledání databáze

Protože nemůžete použít parametr tabulky (ne na SQL Server 2008), zkuste předat bod CSV a nechte uloženou proceduru rozdělit jej do řádků.

Existuje mnoho způsobů, jak rozdělit řetězec na SQL Server. Tento článek popisuje výhody a nevýhody téměř každé metody:

"Pole a seznamy v SQL Server 2005 a novějších, když parametry hodnoty tabulky nefungují Cut it“ od Erlanda Sommarskoga

Musíte vytvořit funkci rozdělení. Takto lze použít funkci rozdělení:

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

Dávám přednost přístupu číselné tabulky k rozdělení řetězce v TSQL ale existuje mnoho způsobů, jak rozdělit řetězce na SQL Server, viz předchozí odkaz, který vysvětluje výhody a nevýhody každého z nich.

Aby metoda Numbers Table fungovala, musíte provést toto jednorázové nastavení časového rozvrhu, které vytvoří tabulku Numbers který obsahuje řádky od 1 do 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)

Jakmile je tabulka Čísla nastavena, vytvořte tuto funkci rozdělení:

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 

Nyní můžete snadno rozdělit řetězec oddělený mezerami do tabulky a připojit se k ní nebo ji použít, jak potřebujete. Tyto kódy jsou založeny na poslední úpravě otázky 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

VÝSTUP:

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)


  1. Výchozí hodnota pro postgresovou funkci sloupce s argumentem

  2. GROUP BY neodstraňuje duplikáty

  3. Poskytuje nástroj mysql CLI způsob, jak zobrazit binární data způsobem přátelským ke konzole?

  4. Použijte hodnotu řetězcové proměnné ve smyčce SQL FOR-IN (SELECT).