SQL-对IN子句使用变量

SQL-对IN子句使用变量,sql,sql-server,Sql,Sql Server,我希望做如下工作: declare @FrameNumber nvarchar(20) set @FrameNumber = '(p1, p2)' select from myTable where c1 in @FrameNumber 正确的语法是什么 (注意:我需要将@FrameNumber的值作为参数传递给存储过程…因此我必须至少使用字符串“p1,p2”) 我们将预先确定并回答与SQL 7兼容的问题,但SQL 2005就足够了 DECLARE @FrameNumbers TABLE (

我希望做如下工作:

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

select from myTable where c1 in @FrameNumber
正确的语法是什么


(注意:我需要将@FrameNumber的值作为参数传递给存储过程…因此我必须至少使用字符串“p1,p2”)

我们将预先确定并回答与SQL 7兼容的问题,但SQL 2005就足够了

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
        )
用法

SELECT * FROM table WHERE id IN (func_ParseStringToTable(@ids))

什么版本的SQL Server


如果您在2008年,您可能能够使用表数据类型。把这些事情简化了很多

如果您使用的是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)
——拆分
声明@textXML
声明@data NVARCHAR(最大值),
@分隔符NVARCHAR(5)
选择@data='A,B,C',
@分隔符=','
选择@textXML=CAST(“”+REPLACE(@data,@delimiter,)+“”作为XML)
选择T.split.value('.',nvarchar(max)')作为数据
来自@textXML.nodes('/d')T(拆分)
您可以将其作为要从中选择的表


看看

您可以将这些值加载到表变量中,也可以使用动态sql。以下是每种方法的示例:

表变量 备选案文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 @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)

感谢Quassnoi和Sam,此解决方案只是您的解决方案的组合

我有另一个关于拆分函数的解决方案

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

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

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

拆分函数:

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
创建函数fn\u Split(
@字符串VARCHAR(8000)
,@分隔符字符(1)
)
返回@tentable(值VARCHAR(8000))
作为
开始
声明@idx INT
声明@slice VARCHAR(8000)
选择@idx=1
如果len(@String)<1
或者@String为空
返回
而@idx!=0
开始
设置@idx=charindex(@Delimiter,@String)
如果@idx!=0
设置@slice=left(@String,@idx-1)
其他的
设置@slice=@String
如果(len(@slice)>0)
插入@tentable(值)
值(@slice)
设置@String=right(@String,len(@String)-@idx)
如果len(@String)=0
打破
结束
返回
结束

我需要将@FrameNumber的值作为参数传入存储过程。。。因此,我必须在SQL Server 2008中使用字符串“p1,p2”,您可以这样做:“func_ParseStringToTable”不是可识别的内置函数名。@alumb,对,它是一个自定义函数。上面的脚本创建了它。
DECLARE @FrameNumber NVARCHAR(20)
SET @FrameNumber = 'p1,p2'

SELECT * FROM MyTable WHERE ProductCode IN 
(SELECT Value FROM fn_Split(@FrameNumber, ','))
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