SQL-在(@Variable_CommaDelimitedListOfIDS)中使用Select语句的存储过程
我正在创建一个存储过程,希望将逗号分隔的ID列表作为变量传递给该存储过程。我想在select语句中使用ID,例如: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…对于这些情况,我使用此表函数,您可以根据需要进行
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的祸福
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