SQL将多个ID作为一个变量

时间:2017-12-12 16:52:27

标签: sql sql-server

我希望将理论上无限数量的ID作为一个变量传递给存储过程,并让它返回所有匹配的记录。当使用list和IN语句时我得到一个错误,因为ProviderID数据类型是INT,并且它将我的列表视为字符串。

DECLARE @ProviderList varchar(max)
SET @ProviderList = '1001,1002' 

SELECT *
FROM   tblProviders
WHERE  ProviderID IN ( @ProviderList )

--Error: Error converting data type varchar to bigint. when used

将ID分隔如下工作......但由于无法知道将同时搜索多少个ID,因此找到不需要的潜在占位符变量会很麻烦。

DECLARE @ProviderOne varchar(max)
SET @ProviderOne = '1001'

DECLARE @ProviderTwo varchar(max)
SET @ProviderTwo = '1002'

SELECT *
FROM   tblProviders
WHERE  ProviderID IN ( @ProviderOne, @ProviderTwo )

5 个答案:

答案 0 :(得分:2)

有两种方法可以做到这一点。一种是分隔字符串,然后将其拆分。由于我不确定您使用的是哪个版本的SQL Server,因此您可以找到Jeff Moden的分隔字符串拆分器here的副本。

然后你可以做类似的事情:

SELECT *
FROM MyTable MT
WHERE MT.MyValues IN (SELECT Item FROM dbo.delimitedSplit8k(@DelimString,',');

另一种方法是使用自定义表值类型。您可以在此处创建表格形式的数据类型。所以,例如:

CREATE TYPE IDs AS TABLE (ID int);
GO

DECLARE @ID IDs;
INSERT INTO @ID
VALUES (1),(2),(3)

SELECT *
FROM MyTable MT
WHERE MT.MyValues IN (SELECT ID FROM @ID);
GO
--Clean up
--DROP TYPE IDs;

如有任何问题,请发表评论。

答案 1 :(得分:1)

最好的方法可能是查询字符串并使用动态SQL。这允许优化器编译查询以实现最佳执行。这种方法是将id列表直接插入到字符串中。当然,如果列表来自用户输入,这可能是一个非常糟糕的主意,因为这种方法会引入SQL注入的风险。

另一种方法是拆分字符串。最新版本的SQL Server(2016+)具有string_split()(或者您可以非常轻松地在Web上找到UDF):

SELECT p.*
FROM tblProviders p
WHERE p.ProviderID IN (SELECT string_split(@ProviderList, ',') )

答案 2 :(得分:0)

您可以接受输入为csv,然后您可以将csv转换为list并按参数

传递
SELECT *
FROM   tblProviders
WHERE  ProviderID IN  (SELECT * FROM dbo.CSVToLIst(@CSV))

CSV列出功能

CREATE FUNCTION dbo.CSVToList (@CSV varchar(3000)) 
    RETURNS @Result TABLE (Value varchar(30))
AS   
BEGIN
    DECLARE @List TABLE
    (
        Value varchar(30)
    )

    DECLARE
        @Value varchar(30),
        @Pos int

    SET @CSV = LTRIM(RTRIM(@CSV))+ ','
    SET @Pos = CHARINDEX(',', @CSV, 1)

    IF REPLACE(@CSV, ',', '') <> ''
    BEGIN
        WHILE @Pos > 0
        BEGIN
            SET @Value = LTRIM(RTRIM(LEFT(@CSV, @Pos - 1)))

            IF @Value <> ''
                INSERT INTO @List (Value) VALUES (@Value) 

            SET @CSV = RIGHT(@CSV, LEN(@CSV) - @Pos)
            SET @Pos = CHARINDEX(',', @CSV, 1)
        END
    END     

    INSERT @Result
    SELECT
        Value
    FROM
        @List

    RETURN
END

答案 3 :(得分:0)

如果您使用的是SQL Server 2016或更高版本,或者使用Azure SQL,则可以使用JSON:

DECLARE @ProviderList varchar(max)
SET @ProviderList = '[1001,1002]' 

SELECT *
FROM   tblProviders
WHERE  ProviderID IN ( SELECT CAST(p.[Value] AS INT) FROM OPENJSON(@ProviderList) p )

这是最快,最安全的方法

答案 4 :(得分:0)

DECLARE @ProviderList varchar(max)

Declare @sqlstring nvarchar(2000)

SET @ProviderList = '100,200,300' 

set @sqlstring = 'SELECT *  FROM temptable where Num_Key in ('  + @ProviderList + ')'

--select @sqlstring

execute sp_executesql @sqlstring