Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.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-在(@Variable_CommaDelimitedListOfIDS)中使用Select语句的存储过程_Sql_Sql Server_Sql Server 2008_Stored Procedures - Fatal编程技术网

SQL-在(@Variable_CommaDelimitedListOfIDS)中使用Select语句的存储过程

SQL-在(@Variable_CommaDelimitedListOfIDS)中使用Select语句的存储过程,sql,sql-server,sql-server-2008,stored-procedures,Sql,Sql Server,Sql Server 2008,Stored Procedures,我正在创建一个存储过程,希望将逗号分隔的ID列表作为变量传递给该存储过程。我想在select语句中使用ID,例如: Create Procedure up_TEST @Ids VARCHAR(MAX) AS SELECT * FROM ATable a WHERE a.Id IN(@Ids) 显然,我得到的错误是,@Ids是一个varchar而不是INT,但如何转换逗号分隔的列表?一种方法可以拆分ID并将其插入临时表中,而不是在子句中使用SQL…对于这些情况,我使用此表函数,您可以根据需要进行

我正在创建一个存储过程,希望将逗号分隔的ID列表作为变量传递给该存储过程。我想在select语句中使用ID,例如:

Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN(@Ids)

显然,我得到的错误是,
@Ids
是一个varchar而不是INT,但如何转换逗号分隔的列表?

一种方法可以拆分ID并将其插入临时表中,而不是在子句中使用SQL…

对于这些情况,我使用此表函数,您可以根据需要进行调整:

CREATE FUNCTION dbo.f_params_to_list (@par VARCHAR(500))
returns @result TABLE (value VARCHAR(30))
AS  
begin
     DECLARE @TempList table
          (
          value VARCHAR(30)
          )

     DECLARE @Value varchar(30), @Pos int

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

     IF REPLACE(@par, ',', '') <> ''
     BEGIN
          WHILE @Pos > 0
          BEGIN
               SET @Value = LTRIM(RTRIM(LEFT(@par, @Pos - 1)))
               IF @Value <> ''
               BEGIN
                    INSERT INTO @TempList (value) VALUES (@Value) --Use Appropriate conversion
               END
               SET @par = RIGHT(@par, LEN(@par) - @Pos)
               SET @Pos = CHARINDEX(',', @par, 1)

          END
     END    
     INSERT @result
     SELECT value 
        FROM @TempList
     RETURN
END    

如果你有这个问题,你应该阅读Sommarskog的文章

我建议:

  • Sql Server中的数组和列表
  • 动态SQL的祸福

既然您使用的是SQL Server 2008,请查看。

使用表值参数(SQL Server 2008中新增的)。通过创建实际表格参数类型进行设置:

CREATE TYPE IntTableType AS TABLE (ID INTEGER PRIMARY KEY)
你的程序是:

Create Procedure up_TEST
    @Ids IntTableType READONLY
AS

SELECT * 
    FROM ATable a
    WHERE a.Id IN (SELECT ID FROM @Ids)

RETURN 0
GO
若不能使用表值参数,请参阅:,那个么在SQL Server中有很多方法可以拆分字符串。本文介绍了几乎每种方法的优缺点:

您需要创建一个拆分函数。这就是拆分函数的使用方式:

SELECT
    *
    FROM YourTable                               y
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
但是在SQLServer中有很多方法可以分割字符串,请参见前面的链接,其中解释了每种方法的优缺点

要使Numbers表方法起作用,您需要执行此一次性表设置,它将创建一个包含1到10000行的表
Numbers

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
设置数字表后,创建此拆分函数:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
    ,@List     varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN 
(

    ----------------
    --SINGLE QUERY-- --this will not return empty rows
    ----------------
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''

);
GO 

今天似乎每个人都在做这样的事情


看一看-这是一种处理带分隔符的输入变量的方法,通过连接数字/计数表(如果尚未连接,则在数据库中拥有该表是一件好事)来提供包含拆分项目的结果集。然后,这将为您提供一个简单的结果集,您可以根据法线加入该结果集

+1-如果您想查看各种技术的性能比较(CSV与表值参数与XML),我不久前在博客中写道:@AdaTheDev,根据您的链接,为什么要为CustomerID创建一个新的表参数类型,如
create type CustomerIDTableType AS TABLE(ID INTEGER主键)这样做可能更易于重用:
createtype IntTableType AS TABLE(ID INTEGER主键)
并使用它传递任何integers@KM-我已经回复了(你的?)博客中的评论。当然,没有理由使用类型名称——我只是演示了一个非常具体的场景作为示例,因此完全同意使用更通用的类型是好的:)欢迎使用stackoverflow。我想你误解了这个问题。上面的方法不适用于多个ID的列表(这也是一个已经回答过的老问题:)。
CREATE PROCEDURE PROCEDURENAME
@Id Numeric(18,0)
AS
BEGIN
    SELECT * FROM tableName
    WHERE tableName.Id IN (@Id)
END
Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN (SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids))
CREATE PROCEDURE PROCEDURENAME
@Id Numeric(18,0)
AS
BEGIN
    SELECT * FROM tableName
    WHERE tableName.Id IN (@Id)
END