我正在创建一个存储过程,我想将其作为变量传递给逗号分隔的ID列表。我想将Ids用于select语句,例如:
Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN(@Ids)
显然我得到@Ids
是varchar而不是INT的错误,但是如何转换逗号分隔列表?
答案 0 :(得分:4)
由于您使用的是SQL Server 2008,请查看table-valued parameters。
答案 1 :(得分:3)
对于这些情况,我使用此表函数,您可以根据自己的需要进行调整:
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
在您的存储过程中,您可以像这样使用它:
Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN(SELECT value FROM dbo.f_params_to_list(@Ids))
答案 2 :(得分:2)
使用表值参数(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
如果您不能使用表值参数,请参阅:"Arrays and Lists in SQL Server 2008 Using Table-Valued Parameters" by Erland Sommarskog ,那么有很多方法可以在SQL Server中拆分字符串。本文涵盖几乎所有方法的PRO和CON:
您需要创建拆分功能。这就是如何使用拆分功能:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
I prefer the number table approach to split a string in TSQL但是有很多方法可以在SQL Server中拆分字符串,请参阅上一个链接,该链接解释了每个链接的PRO和CON。
要使Numbers Table方法起作用,您需要进行一次性表设置,这将创建一个包含1到10,000行的表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)
设置Numbers表后,创建此拆分功能:
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
您现在可以轻松地将CSV字符串拆分为表格并加入其中:
Create Procedure up_TEST
@Ids VARCHAR(MAX)
AS
SELECT * FROM ATable a
WHERE a.Id IN (SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids))
答案 3 :(得分:1)
答案 4 :(得分:1)
今天似乎每个人都在做这样的事情!
看一下http://www.sqlteam.com/article/parsing-csv-values-into-multiple-rows - 这是一种处理分隔输入变量的方法,通过连接数字/统计表来提供包含分割项的结果集(这是一个很好的事情。数据库无论如何你还没有)。然后,这会为您提供一个简单的结果集,您可以按照正常情况加入。
答案 5 :(得分:1)
CREATE PROCEDURE PROCEDURENAME
@Id Numeric(18,0)
AS
BEGIN
SELECT * FROM tableName
WHERE tableName.Id IN (@Id)
END
答案 6 :(得分:0)
可以拆分一种方法并将id插入临时表,而不是使用SQL IN子句......