2010-05-19 3 views
2

Как передать строку, разделенную пробелом или запятой, в хранимую процедуру и результат фильтрации? Я пытаюсь сделать что-то вроде -Передача разделительной строки в хранимую процедуру в базу данных поиска

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

Затем хранимой процедуры я хочу сначала

  1. найти все записи с первым или последним именем, как key1
  2. фильтра шаг 1 с первым или последняя имя, подобное key2
  3. шаг фильтра 2 с первым или последним именем, например ключ 3

Другой пример:

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

Если я искать какой-либо после него следует вернуться для каждого?

  1. "разработчик хуг" возвращает 2 строки

  2. "хуг ABC" возвращает 1 строку

  3. "разработчик ABC" возвращает 1 строку

  4. "Привет" возвращает 2 строки

  5. «привет разработчик» возвращает 2 строки

  6. «хуг» возвращает 2 строки

ответ

2

Поскольку вы не можете использовать параметр таблицы (не на SQL Server 2008), попробуйте передать в укусе CSV и иметь хранимую процедуру разбить его на строки для вас ,

Существует много способов разделить строку на SQL Server. В данной статье рассматривается плюсы и минусы просто о каждом методе:

"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 но есть множество способов, чтобы разделить строки в SQL Server, см предыдущей ссылки, объясняющие плюсы и минусы каждого из них.

Для метода Числа таблицы для работы, вы должны сделать это один раз настройки таблицы, которая будет создавать таблицу 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) 

После того как таблица Numbers устанавливается , создать разбитую функцию:

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 

Теперь можно легко разделить пробела разделителей строки в таблицу и присоединиться на него или использовать его, как вам это нужна кода на основе OPS последнего вопрос редактирования:

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) 
+0

Я знаю и могу использовать функции split, но переданные ключевые слова не являются точными значениями, чтобы использовать их при соединении, они могут быть частичными именами/словами. –

+0

обновить ответ на использование 'LIKE' –

+0

. Моя мысль по вашему запросу заключается в том, что она вернется ИЛИ на основе результата вместо AND, я пробовал это раньше, но я хочу запросить что-то вроде ex: имя, фамилию, например key1 и имя, фамилию, такую ​​как key2 И имя, фамилию, как key3, которую я не могу достичь использования split –

1

Вы могли бы попробовать что-то вроде:

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) 

где @test таблица с результатами вашего раскола. Если у вас много столбцов в persondata, вы можете просто вернуть идентификатор из этого запроса и использовать его в качестве подзапроса для того, который фактически возвращает данные, поэтому вам не нужно группировать столько столбцов.

Редактировать: вы также можете использовать курсор и другую переменную temp table/table, но у меня есть аллергическая реакция на курсоры в SP.

Смежные вопросы