2013-07-12 19 views
3

我有这样一个存储过程:在SQL Server更新多行与IN子句

CREATE PROCEDURE Resume 
    @UserID nvarchar(100) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    update Candidate set Approved = 'y' where UserId_I in (@UserID) 
END 
GO 

在这个@UserID是字符串格式。我从代码发送参数@UserID的值为1,2,3作为字符串。

我误差作为

转换nvarchar的值 '1,2,3' 为数据类型int时转换失败。

请解决这个

+4

对'in“的多个单独参数在逻辑上是不同的t来自*发生的*单个*字符串参数,以包含逗号。与几乎所有其他编程语言一样,SQL不会神奇地决定检查字符串并改变它。正确的解决方法是首先不传递字符串 - 传递(理想情况下)表值参数或XML文档 - 设计为包含多个值的东西。毫无疑问,你会得到答案(或接近投票)指向在服务器上创建分割函数,但这确实是错误的方法。 –

回答

2

尝试使用具有比子查询中使用该临时表

DECLARE @userIds NVARCHAR(MAX) 
SET @userIds ='1,2,3,4,5,6' 

CREATE table #TempUser 
(
    userId Int 
) 
DECLARE @SplitOn VARCHAR(1) 
SET @SplitOn = ',' 

While (Charindex(@SplitOn,@userIds)>0) 
Begin 
    Insert Into #TempUser (userId) 
    Select 
     userId = ltrim(rtrim(Substring(@userIds ,1,Charindex(@SplitOn,@userIds)-1))) 
    Set @userIds = Substring(@userIds,Charindex(@SplitOn,@userIds)+1,len(@userIds)) 
End 

Insert Into #TempUser (userId) 
Select Data = ltrim(rtrim(@userIds)) 

SELECT * FROM #TempUser 

现在,您可以更新您的记录更好的性能临时表。

+0

谢谢你的回答 – user2439934

2

请更新使用EXECUTE (Transact-SQL)命令。

CREATE PROCEDURE Resume 
    -- Add the parameters for the stored procedure here 
    @UserID nvarchar(100) 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    -- Insert statements for procedure here 
    exec ('update Candidate set Approved=''y'' where UserId_I in ('[email protected]+')') 
END 
GO 
+0

当然,这也是一个选项,但请注意SQL注入的可能性。 ;-) –

+0

谢谢你的回答 – user2439934

3

你可以用多种方法做到这一点。您可以定义表格类型并通过该表格类型传递用户ID列表(请参阅此问题:INSERT using LIST into Stored Procedure)。

您也可以在WHILE循环中以逗号分隔字符串,并将ID添加到临时表中。那么你可以使用... IN (SELECT UID FROM @tempTable)。粗略的算法:

DECLARE @tempTable TABLE (UID INT) 

WHILE ([Length of @UserID > 0]) 
BEGIN 
    IF ([@UserID contains comma?]) 
    BEGIN 
     [GET STRING UNTIL COMMA] 
     [CONVERT TO INT AND INSERT INTO @tempTable] 
     [REMOVE STRING AND COMMA FROM @UserID] 
    END ELSE 
    BEGIN 
     [CONVERT @UserID TO INT AND INSERT INTO @tempTable] 
     SET @UserID = '' 
    END 
END 

您还可以使用EXEC的做法,但我倾向于不使用EXEC从外界传入的参数 - 你打开你的代码,SQL注入。我要执行的最小检查是@UserID参数是否只包含数字,逗号和空格。

+0

谢谢你的回答 – user2439934

0

发生该错误是因为您不能将字符串(@UserID)用作IN运算符的右侧运算符。 IN运算符需要一个SET作为右手操作符 - 在这种情况下,您需要一组int来判断UserId_I是否为该集合的一部分。

您可以在这里执行两项操作:为@ UserID参数使用表值参数,或者编写将@ UserID字符串转换/拆分为表/整数集的函数,其中情况下,你会得到这样的:

...WHERE @UserId_I IN dbo.ParseIntSet(@UserId); 
0

你可以试试下面给出一个演示...

CREATE PROCEDURE [dbo].[Proc_Name] @CSVConnectivityIds NVARCHAR(MAX) 
WHILE len(@CSVConnectivityIds) > 0 
    BEGIN 
     INSERT INTO tblName 
     VALUES (left(@CSVConnectivityIds, charindex(',', @CSVConnectivityIds + ',') - 1)) 
     SET @CSVConnectivityIds = stuff(@CSVConnectivityIds, 1, charindex(',', @CSVConnectivityIds + ','), '') 
    END 

我希望这将有助于你

1

对于拆分@UserID参数,您可以使用XQuery value() method

CREATE PROCEDURE Resume 
    @UserID nvarchar(100) 
AS 
BEGIN 
    SET NOCOUNT ON; 

    UPDATE Candidate 
    SET Approved = 'y' 
    WHERE UserId_I IN 
    (SELECT Split.a.value('.', 'int') 
    FROM (SELECT CAST ('<M>' + REPLACE(@UserID , ',', '</M><M>') + '</M>' AS XML) AS val  
      ) AS A CROSS APPLY val.nodes('/M') AS Split(a) 
    ) 
END 
GO 

见演示SQLFiddle