Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL将多个ID作为一个变量传递_Sql_Sql Server - Fatal编程技术网

SQL将多个ID作为一个变量传递

SQL将多个ID作为一个变量传递,sql,sql-server,Sql,Sql Server,我希望将理论上无限数量的ID作为一个变量传递给存储过程,并让它返回所有匹配的记录。当使用list和IN语句时,我得到一个错误,因为ProviderIDdatatype是INT,它将我的列表视为字符串 DECLARE @ProviderList varchar(max) SET @ProviderList = '1001,1002' SELECT * FROM tblProviders WHERE ProviderID IN ( @ProviderList ) --Error: Err

我希望将理论上无限数量的ID作为一个变量传递给存储过程,并让它返回所有匹配的记录。当使用list和IN语句时,我得到一个错误,因为
ProviderID
datatype是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 )

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

另一种方法是拆分字符串。SQL Server(2016+)的最新版本具有
string\u split()
(或者您可以很容易地在web上找到UDF):


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

另一种方法是拆分字符串。SQL Server(2016+)的最新版本具有
string\u split()
(或者您可以很容易地在web上找到UDF):


您可以接受作为csv的输入,然后可以将csv转换为列表并作为参数传递

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
创建函数dbo.CSVToList(@CSV varchar(3000))
返回@Result表(值varchar(30))
作为
开始
声明@List表
(
varchar值(30)
)
声明
@值varchar(30),
@位置int
设置@CSV=LTRIM(RTRIM(@CSV))+','
设置@Pos=CHARINDEX(“,”,@CSV,1)
如果替换(@CSV,“,”)”
开始
而@Pos>0
开始
设置@Value=LTRIM(RTRIM(左(@CSV,@Pos-1)))
如果@Value''
插入@List(Value)值(@Value)
设置@CSV=RIGHT(@CSV,LEN(@CSV)-@Pos)
设置@Pos=CHARINDEX(“,”,@CSV,1)
结束
结束
插入@Result
挑选
价值
从…起
@名单
返回
结束

您可以接受作为csv的输入,然后可以将csv转换为列表并作为参数传递

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
创建函数dbo.CSVToList(@CSV varchar(3000))
返回@Result表(值varchar(30))
作为
开始
声明@List表
(
varchar值(30)
)
声明
@值varchar(30),
@位置int
设置@CSV=LTRIM(RTRIM(@CSV))+','
设置@Pos=CHARINDEX(“,”,@CSV,1)
如果替换(@CSV,“,”)”
开始
而@Pos>0
开始
设置@Value=LTRIM(RTRIM(左(@CSV,@Pos-1)))
如果@Value''
插入@List(Value)值(@Value)
设置@CSV=RIGHT(@CSV,LEN(@CSV)-@Pos)
设置@Pos=CHARINDEX(“,”,@CSV,1)
结束
结束
插入@Result
挑选
价值
从…起
@名单
返回
结束

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

然后,您可以执行以下操作:

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;

任何问题,请发表评论。

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

然后,您可以执行以下操作:

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;

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

如果您使用的是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 )

如果您使用的是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 )
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

这是可用的最快、最安全的方法

您的数据似乎需要整数。您可以在中添加强制转换(选择强制转换(值为int)…您的数据似乎需要整数。您可以在中添加强制转换(选择强制转换(值为int))…我认为string\u split更适合于此项工作,尽管我没有测试bothYep的性能,但string\u也可以。我仍然更喜欢使用json,因为我可以使用ISJSON函数确保在开始在查询中使用数字之前就有一组有效的数字。我认为string\u split更适合于此项工作,尽管我没有st bothYep的性能也可以拆分字符串。我仍然更喜欢使用json,因为我可以使用ISJSON函数来确保我有一组有效的数字,甚至在开始在查询中使用它们之前。SQL Server版本SQL Server版本如果你真的在寻找“理论上无限”的话,这是正确的答案ids.在SQL Server(和大多数数据库)中,一条语句的长度最大。如果有几十个或几百个条目,您可能不会有问题,但如果有几千个条目,您几乎肯定不会有问题,而使用表值参数是唯一的(合理的)向前看。这也不值得。我链接的拆分器最多只能处理8000个字符的分隔字符串。如果您真的在寻找“理论上无限”的ID,这是正确的答案。在SQL Server(和大多数数据库)中,一条语句有一个最大长度。如果你有几十条或几百条语句,你可能没问题,但如果你有几千条语句,你就可以了
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