SQL поиск из строки CSV - PullRequest
       1

SQL поиск из строки CSV

3 голосов
/ 09 февраля 2012

Я делаю страницу поиска, где я должен искать несколько полей в одном текстовом поле. поэтому я получу текст поиска в виде строки CSV в моей хранимой процедуре

Моя таблица как ниже

ID  Name          age   
5   bob           23    
6   bod.harry     34    
7   charles       44    

Мне нужен SQL-запрос как этот

declare @searchtext='bob,harry,charley'
select * from employee where  name like (@searchtext) 

этот запрос должен возвращать обе эти записи (id 5 и 6)

Ответы [ 5 ]

3 голосов
/ 09 февраля 2012

Вы можете использовать этот способ в хранимой процедуре,

declare @searchtext varchar(1000)

set searchtext ='bob,harry,charley'

declare @filter varchar(2000)

set @filter = '(name LIKE ''%' + replace('bob,harry,charley',',','%'' OR name LIKE ''%') + '%'')'

exec
('
    select *
    from mytab
    where ' + @filter + '
'
)
3 голосов
/ 09 февраля 2012

Используйте (или адаптируйте) эту функцию разделения:

ALTER FUNCTION [dbo].CsvToList(@SplitOn  char(1), @List varchar(8000))
RETURNS TABLE
AS
RETURN 
(
    SELECT
        ROW_NUMBER() OVER(ORDER BY number) AS RowNumber
            ,LTRIM(RTRIM(SUBSTRING(ListValue, number+1, CHARINDEX(@SplitOn, ListValue, number+1)-number - 1))) AS ListValue
        FROM (
                 SELECT @SplitOn + @List + @SplitOn AS ListValue
             ) AS InnerQuery
            INNER JOIN master.dbo.spt_values n ON n.Number < LEN(InnerQuery.ListValue)
        WHERE SUBSTRING(ListValue, number, 1) = @SplitOn
        AND n.type = 'P'
);
GO 

использование

declare @searchtext='bob,harry,charley'
select DISTINCT * from employee e
JOIN dbo.csvToList(',', @searchtext) f
  ON f.ListValue = e.name
0 голосов
/ 25 июня 2013

Приведенная выше версия [dbo] .CsvToList не работает с длинной входной строкой с большим количеством разделителей.Таблица spt_values, где type = 'P', имеет ограниченное количество записей.В моем случае функция вернула 16 строк вместо 66. Некоторые советуют создать собственную таблицу с числами.Я использовал другую версию этой функции, которую я скопировал из другого места:

CREATE FUNCTION [dbo].[fngCsvToList](@SplitOn char(1), @List varchar(8000))
RETURNS @Result TABLE (ListValue varchar(100))
AS
BEGIN 
  DECLARE @str VARCHAR(20) 
  DECLARE @ind Int 
  IF(@List is not null) 
  BEGIN 
    SET @List = REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(@List)), CHAR(10), ''),    CHAR(13), ''), CHAR(9), '')

        SET @ind = CharIndex(@SplitOn, @List) 
        WHILE @ind > 0 
        BEGIN 
              SET @str = SUBSTRING(@List, 1, @ind-1) 
              SET @List = SUBSTRING(@List, @ind+1, LEN(@List)-@ind) 
              INSERT INTO @Result values (LTRIM(RTRIM(@str)))

              SET @ind = CharIndex(',',@List) 
        END 

   SET @str = @List
        INSERT INTO @Result values (LTRIM(RTRIM(@str) ))
  END 
  RETURN 
END
0 голосов
/ 09 февраля 2012

Если я не ошибаюсь, Sql-Server не поддерживает Regex. Вы можете использовать табличные параметры . Если вы используете Entity Framework, вы можете сделать это.

var dc = new MyContext();
var result = dc.employees.Where(x => new [] { "bob", "harry", "charley" }.Contains(x.name));

и, наконец, вы можете построить следующее

select * from employee where  name in (@Param1, @Param2, @Param3, @Param4)

EDIT

Я настоятельно не рекомендую вам использовать CSV из-за падения производительности (вы должны проанализировать CSV) и возможности ошибок (рассмотрим этот CSV Foo,Bar,"Foo with, comma","comma, "" and quote")

P.S. Если вы используете параметр с табличным значением при назначении значения, используйте DataTable в качестве источника.

0 голосов
/ 09 февраля 2012

Вам нужно разбить @searchtext на несколько строк, по одной для каждого имени. Это возможно в TSQL, но может быть проще в коде вашего приложения. Затем вы можете сравнить их с вашим полем имени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...