#sql #sql-server #tsql #stored-procedures #sql-function
#sql #sql-server #tsql #хранимые процедуры #sql-функция
Вопрос:
У меня есть строка, подобная этой:
@Values VARCHAR(1000)
SET @Values = 'one, two, three'
Я хочу использовать эту строку в WHERE
предложении с IN
оператором.
Для этого я использую следующую табличную функцию.
ALTER FUNCTION [dbo].[FN_RPT_CommaSeperated]
(@StringInput VARCHAR(8000),
@Delimiter NVARCHAR(1))
RETURNS @OutputTable TABLE ( [String] VARCHAR(10) )
AS
BEGIN
DECLARE @String VARCHAR(10)
WHILE LEN(@StringInput) > 0
BEGIN
SET @String = LEFT(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput) - 1, -1),
LEN(@StringInput)))
SET @StringInput = SUBSTRING(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput), 0),
LEN(@StringInput)) 1, LEN(@StringInput))
INSERT INTO @OutputTable ([String])
VALUES ('''' @String '''')
END
RETURN
END
Эта функция возвращает значения ожидаемым образом. Но все же моя хранимая процедура не выдает данные, как ожидалось.
В хранимой процедуре, которую я использую следующим образом:
WHERE
TD.CaseId IN (SELECT * FROM [FN_RPT_CommaSeperated] (@Values,','))
В любом случае, когда я жестко кодирую подобные значения в хранимой процедуре, она возвращает ожидаемый результат.
WHERE
TD.CaseId IN ('one', 'two', 'three')
Есть идеи, как получить результат с помощью функции?
Ответ №1:
Уже есть функция с табличным значением, встроенная в SQL Server, начиная с SQL Server 2016. String_Split
DECLARE @Values VARCHAR(1000)
SET @Values = 'one, two, three'
SELECT value FROM STRING_SPLIT(@Values, ',');
Вы можете сделать что-то вроде приведенного ниже:
WHERE
TD.CaseId IN (SELECT value FROM STRING_SPLIT(@Values));
Ответ №2:
Вы близки, но поскольку теперь у вас есть таблица, вы можете использовать что-то вроде:
WHERE exists
(select * from [FN_RPT_CommaSeperated] (@Values,',') where [string]=TD.CaseId)
Комментарии:
1. Я не понял здесь часть «where [string]= TD.CaseID». почему это используется?
2. Что здесь [строка] ?
3. Это имя столбца, возвращаемого вашей функцией.
4. Когда я использую это снова, ничего не возвращается. Но если я использую только это, всегда возвращаются данные для всех регистров. ГДЕ существует (выберите * из [FN_RPT_CommaSeperated] (@Values,’,’)
5. Мне удалось получить данные, используя предложение ur и небольшое изменение функции.
Ответ №3:
Я немного изменил функцию и предложение WHERE в SP, чтобы получить ожидаемый результат. Это работает нормально.
ALTER FUNCTION [dbo].[FN_RPT_CommaSeperated]
(@StringInput VARCHAR(8000),
@Delimiter NVARCHAR(1))
RETURNS @OutputTable TABLE ( [String] VARCHAR(10) )
AS
BEGIN
DECLARE @String VARCHAR(10)
WHILE LEN(@StringInput) > 0
BEGIN
SET @String = LEFT(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput) - 1, -1),
LEN(@StringInput)))
SET @StringInput = SUBSTRING(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput), 0),
LEN(@StringInput)) 1, LEN(@StringInput))
**INSERT INTO @OutputTable ([String])
VALUES (@String)**
END
RETURN
END
В хранимой процедуре изменилось следующим образом.
WHERE
**exists
(select * from [FN_RPT_CommaSeperated_Kiosk] (@KioskId,',') where [String] = TD.CaseId)**
Ответ №4:
Вам нужно небольшое изменение в вашей функции
ALTER FUNCTION [dbo].[FN_RPT_CommaSeperated]
(@StringInput VARCHAR(8000),
@Delimiter NVARCHAR(1))
RETURNS @OutputTable TABLE ( [String] VARCHAR(10) )
AS
BEGIN
DECLARE @String VARCHAR(10)
WHILE LEN(@StringInput) > 0
BEGIN
SET @String = LEFT(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput) - 1, -1),
LEN(@StringInput)))
SET @StringInput = SUBSTRING(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput), 0),
LEN(@StringInput)) 1, LEN(@StringInput))
INSERT INTO @OutputTable ([String])
VALUES ('' @String '')
END
RETURN
END
используйте VALUES ('' @String '')
вместо VALUES ('''' @String '''')