SQL - использование переменной для предложения IN - PullRequest
3 голосов
/ 22 декабря 2009

Я хочу сделать что-то вроде следующего:

declare @FrameNumber nvarchar(20)
set @FrameNumber = '(p1, p2)'

select from myTable where c1 in @FrameNumber

Какой правильный синтаксис для этого?

(для заметки: мне нужно передать значение @FrameNumber в качестве параметра хранимой процедуре ... поэтому я должен по крайней мере использовать строку "p1, p2")

подтвердит и ответит, что он совместим с SQL 7, но SQL 2005 будет достаточно.

Ответы [ 7 ]

9 голосов
/ 22 декабря 2009
DECLARE @FrameNumbers TABLE (code NVARCHAR(20) PRIMARY KEY)

INSERT
INTO   @framenumbers
VALUES ('p1')

INSERT
INTO   @framenumbers
VALUES ('p2')

SELECT  *
FROM    mytable
WHERE   c1 IN
        (
        SELECT  code
        FROM    @framenumbers
        )
2 голосов
/ 22 декабря 2009
CREATE FUNCTION [dbo].[func_ParseStringToTable] (@stringIN varchar(2000)) 
RETURNS @tOUT TABLE(RoomID int) AS
BEGIN
DECLARE @pos int
SET @pos=CHARINDEX(',',@StringIN)
WHILE @pos>0
     BEGIN
     INSERT @tOUT(RoomID) SELECT LEFT(@StringIN,CHARINDEX(',',@StringIN)-1)
     SET @stringIN = SUBSTRING(@StringIN,CHARINDEX(',',@StringIN)+1,LEN(@StringIN))
     SET @pos=CHARINDEX(',',@StringIN)
     END
IF LEN(@StringIN)>0
     BEGIN
     INSERT @tOUT(RoomID) SELECT @StringIN
     END
RETURN 
END

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

SELECT * FROM table WHERE id IN (func_ParseStringToTable(@ids))
1 голос
/ 23 марта 2017

У меня есть другое решение с функцией разделения,

DECLARE @FrameNumber NVARCHAR(20)
SET @FrameNumber = 'p1,p2'

SELECT * FROM MyTable WHERE ProductCode IN 
(SELECT Value FROM fn_Split(@FrameNumber, ','))

Выход:

enter image description here

Функции разделения:

CREATE FUNCTION fn_Split (
    @String VARCHAR(8000)
    ,@Delimiter CHAR(1)
    )
RETURNS @temptable TABLE (Value VARCHAR(8000))
AS
BEGIN
    DECLARE @idx INT
    DECLARE @slice VARCHAR(8000)

    SELECT @idx = 1

    IF len(@String) < 1
        OR @String IS NULL
        RETURN

    WHILE @idx != 0
    BEGIN
        SET @idx = charindex(@Delimiter, @String)

        IF @idx != 0
            SET @slice = left(@String, @idx - 1)
        ELSE
            SET @slice = @String

        IF (len(@slice) > 0)
            INSERT INTO @temptable (Value)
            VALUES (@slice)

        SET @String = right(@String, len(@String) - @idx)

        IF len(@String) = 0
            BREAK
    END

    RETURN
END
1 голос
/ 22 декабря 2009

Вы можете поместить эти значения в табличную переменную или использовать динамический SQL Вот примеры каждого из них:

ТАБЛИЦА ПЕРЕМЕННАЯ

DECLARE @FrameNumbers TABLE (
    Frame NVARCHAR(20)
)

INSERT INTO @FrameNumbers (
    Frame
)
SELECT 'p1'
UNION ALL SELECT 'p2'

вариант 1:

SELECT * FROM myTable WHERE c1 in (
    SELECT Frame
    FROM @FrameNumbers
)

вариант 2:

SELECT
    m.*
FROM myTable m
INNER JOIN @FrameNumbers f ON f.Frame = m.c1

Все хорошо, но это мое любимое:

ДИНАМИЧЕСКИЙ SQL

DECLARE 
@FrameNumber nvarchar(20),
@sql nvarchar(max),
@ParamDef nvarchar(1000)

SET @FrameNumber = '(p1, p2)'

SET @sql = N'SELECT FROM myTable WHERE c1 IN ' + @FrameNumber

EXECUTE dbo.sp_ExecuteSQL @sql
0 голосов
/ 22 декабря 2009

окончательное решение:

DECLARE @FrameNumbers TABLE (FrameNumber NVARCHAR(20) PRIMARY KEY)

DECLARE @pos int
SET @pos=CHARINDEX(',',@FrameNumber)
WHILE @pos>0 BEGIN
     INSERT @FrameNumbers SELECT LEFT(@FrameNumber,CHARINDEX(',',@FrameNumber)-1)
     SET @FrameNumber = SUBSTRING(@FrameNumber,CHARINDEX(',',@FrameNumber)+1,LEN(@FrameNumber))
     SET @pos=CHARINDEX(',',@FrameNumber)
END
IF LEN(@FrameNumber)>0 BEGIN
     INSERT @FrameNumbers SELECT @FrameNumber
END

select from myTable where c1 in (select FrameNumber from @FrameNumbers)

спасибо Кассной и Сэму, это решение - просто комбинация ваших решений.

0 голосов
/ 22 декабря 2009

Если вы используете Sql Server 2005+, взгляните на это

--Split
DECLARE @textXML XML
DECLARE @data NVARCHAR(MAX), 
        @delimiter NVARCHAR(5)

SELECT  @data = 'A,B,C',
        @delimiter = ','

SELECT    @textXML = CAST('<d>' + REPLACE(@data, @delimiter, '</d><d>') + '</d>' AS XML)
SELECT  T.split.value('.', 'nvarchar(max)') AS data
FROM    @textXML.nodes('/d') T(split)

Вы можете выбрать его из таблицы.

Посмотрите на Поддержка XML в Microsoft SQL Server 2005

0 голосов
/ 22 декабря 2009

какая версия SQL Server?

Если вы находитесь в 2008 году, вы можете использовать типы данных таблиц. Упрощает эти вещи много.

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