SQL Сохраненная процедура LIKE
Это простой вопрос, и я не могу представить себе решение.
У меня это определено в моей хранимой процедуре:
@communityDesc varchar(255) = NULL
@communityDesc - это "aaa, bbb, ccc"
и в моем фактическом запросе я пытаюсь использовать IN
WHERE AREA IN (@communityDesc)
но это не сработает, потому что мои запятые находятся внутри строки вместо таких, как "aaa", "bbb", "ccc"
Итак, мой вопрос: есть ли что-нибудь, что я могу сделать для @communityDesc, поэтому он будет работать с моей инструкцией IN, например, форматировать строку?
Ответы
Ответ 1
сначала вы больше всего создаете функцию для разделения строки, например, такой код
CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
@returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE CHARINDEX(',', @stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
INSERT INTO @returnList
SELECT @name
SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)[email protected])
END
INSERT INTO @returnList
SELECT @stringToSplit
RETURN
END
то вы можете использовать эту функцию, например, ваш запрос
WHERE AREA IN (dbo.splitstring(@communityDesc))
Ответ 2
Эта статья может помочь вам в вашей проблеме:
http://sqlperformance.com/2012/07/t-sql-queries/split-strings
В этой статье Аарон Бертран пишет о вашей проблеме.
Это действительно длинный и очень подробный.
Один из способов:
CREATE FUNCTION dbo.SplitStrings_XML
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
GO
С помощью этой функции вы вызываете только:
WHERE AREA IN (SELECT Item FROM dbo.SplitStrings_XML(@communityDesc, N','))
Надеюсь, это поможет вам.
Ответ 3
Самый простой способ использования этой переменной:
SELECT *
FROM something
WHERE ',' + @communityDesc + ',' Like '%,' + AREA + ',%'
это для tsql, для использования оракула ||
для объединения строк
Ответ 4
In
работает только с наборами значений, а не с символами в строке. Чтобы технически ответить на ваш вопрос, единственный способ сделать это - создать набор значений, представляющих три значения: "aaa", "bbb" и "ccc", а затем поместить эти три значения в таблицу (таблица или таблица Temp переменной (в SQL Server), а затем выполнить IN против этого набора значений (в таблице:
declare @Vals table (value varchar(20))
insert @vals(Value) Values('aaa')
insert @vals(Value) Values('bbb')
insert @vals(Value) Values('ccc')
select * from SomeOtherTable
Where SomeColumn IN (Select value from @vals)
Чтобы создать набор, вам нужно создать пустую таблицу temp или таблицу для хранения этого набора значений, проанализировать строку с разделителями-запятыми в отдельные значения и ввести эти отдельные значения в таблицу temp или табличную переменную.
хотя вы не говорите, что если вы используете SQL Server, следующая функция определяется пользователем SQL Server (UDF), которая будет анализировать строку с разделителями и возвращать таблицу с одной строкой для каждого разделительного значения:
если вы создаете UDF, вы будете использовать его следующим образом:
select * from SomeOtherTable
Where SomeColumn IN
(Select sVal from
dbo.ParseSTring(@communityDesc, ','))
/****** Object: UserDefinedFunction [dbo].[ParseString]
Script Date: 4/8/2016 1:53:00 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[ParseString] (@S Text, @delim VarChar(5))
Returns @tOut Table
(ValNum Integer Identity Primary Key,
sVal VarChar(8000))
As
Begin
Declare @dLLen TinyInt -- Length of delimiter
Declare @sWin VarChar(8000)-- Will Contain Window into text string
Declare @wLen Integer -- Length of Window
Declare @wLast TinyInt -- Boolean to indicate processing Last Window
Declare @wPos Integer -- Start Position of Window within Text String
Declare @sVal VarChar(8000)-- String Data to insert into output Table
Declare @BtchSiz Integer -- Maximum Size of Window
Set @BtchSiz = 7900 -- (Reset to smaller values to test routine)
Declare @dPos Integer -- Position within Window of next Delimiter
Declare @Strt Integer -- Start Position of each data value in Window
-- --------------------------------------------------------------
-- ---------------------------
If @delim is Null Set @delim = '|'
If DataLength(@S) = 0 Or
Substring(@S, 1, @BtchSiz) = @delim Return
-- ---------------------------
Select @dLLen = Len(@delim),
@Strt = 1, @wPos = 1,
@sWin = Substring(@S, 1, @BtchSiz)
Select @wLen = Len(@sWin),
@wLast = Case When Len(@sWin) = @BtchSiz
Then 0 Else 1 End,
@dPos = CharIndex(@delim, @sWin, @Strt)
-- ----------------------------
While @Strt <= @wLen
Begin
If @dPos = 0 Begin -- No More delimiters in window
If @wLast = 1 Set @dPos = @wLen + 1
Else Begin
Set @wPos = @wPos + @Strt - 1
Set @sWin = Substring(@S, @wPos, @BtchSiz)
-- -------------------------------------
Select @wLen = Len(@sWin), @Strt = 1,
@wLast = Case When Len(@sWin) = @BtchSiz
Then 0 Else 1 End,
@dPos = CharIndex(@delim, @sWin, 1)
If @dPos = 0 Set @dPos = @wLen + 1
End
End
-- -------------------------------
Set @sVal = LTrim(Substring(@sWin, @Strt, @dPos - @Strt))
Insert @tOut (sVal) Values (@sVal)
-- -------------------------------
-- Move @Strt to char after last delimiter
Set @Strt = @dPos + @dLLen
Set @dPos = CharIndex(@delim, @sWin, @Strt)
End
Return
End
Ответ 5
Вы можете сделать это, разделив строку, используя функцию разделения здесь. Функция возвращает таблицу, содержащую один столбец, который содержит ваши токены (т.е. "Aaa", "bbb"...).
Ваш запрос должен выглядеть следующим образом:
-- get the splits
SELECT Name INTO #someTemp
FROM dbo.splitstring(@communityDesc)
-- get data where area in within description
SELECT 1
FROM yourTable T
WHERE EXISTS (SELECT 1 FROM #someTemp tmp WHERE T.Area = tmp.Name)
Ответ 6
Другой подход - использовать CHARINDEX(). Однако использование функции в предложении WHERE приведет к замедлению производительности.
WHERE CHARINDEX(','+area+',',','[email protected]+',')> 0
Если поле области равно 3 буквам, вы можете упростить это.
WHERE CHARINDEX(area,@CommunityDec)> 0
Это быстрое решение, но также и разрыв остановки. Лучшее решение - изменить подход поиска строк, чтобы построить таблицу с одной строкой для каждого критерия поиска и использовать JOIN или sub-запрос.
Ответ 7
Вы можете просто разбить этот csv с помощью XML и использовать его для фильтрации в вашем запросе. Нет необходимости использовать определенную пользователем функцию или @Table_Valiable или #Temp_Table здесь.
DECLARE @xml as xml,@communityDesc varchar(255) = 'aaa,bbb,ccc'
SET @xml = cast(('<X>'+replace(@communityDesc,',' ,'</X><X>')+'</X>') as xml)
SELECT * FROM TABLE1
WHERE AREA IN (
SELECT N.value('.', 'varchar(10)') as value FROM @xml.nodes('X') as T(N)
)
Если вам нужны эти значения разделения в дальнейшем процессе, вы можете вставить это в #table_Variable или #Temp_Table и использовать их.