SPROC用逗号分隔的输入删除多行?

时间:2009-11-13 20:20:43

标签: sql sql-server csv

我创建了一个sproc来删除多个记录,方法是接受以逗号分隔的ID列表为varchar,并使用IN来尝试删除 - 不起作用:

ALTER PROCEDURE [dbo].[sp_DeleteItemsFromItemCategories]
 @UserID bigint,
 @ItemsList varchar(8000)
AS
BEGIN
 -- SET NOCOUNT ON added to prevent extra result sets from
 -- interfering with SELECT statements.
 SET NOCOUNT ON;
 DELETE 
 FROM tbl_ItemFoldersLnk
 WHERE LineItemID IN (SELECT LineItemID FROM tbl_ItemFoldersLnk WHERE LineItemID IN (@ItemsList))
END

最初我有... IN(@ItemList)但仍然无效。错误是“将数据类型varchar转换为bigint时出错。”

我确实有其他SPROCS迭代逗号分隔列表,我可以用它来删除,但后来我为每一行运行一个删除函数。

建议?

感谢。

5 个答案:

答案 0 :(得分:1)

Arrays and lists in SQL Server

您需要将CSV更改为表格(根据文章)并加入以过滤。

你实际上是在比较ID列和字符串“1,45,67”,这不是一个整数......

答案 1 :(得分:1)

假设字符串是以逗号分隔的整数值列表,请尝试:

SET @ ItemsList =','+ replace(@ItemsList,'','')+','

现在列表中应该包含逗号分隔的每个数字,并删除多余的空格。删除查询变为

删除  FROM tbl_ItemFoldersLnk  在哪里Charindex(','+ ltrim(str(LineItemID))+',',@ ItemList)> 0

性能不会很好,但它会完成工作......

答案 2 :(得分:0)

您可以将输入字符串解析为离散值(例如,通过用户定义的函数),将这些值插入到表对象中,然后发出一个删除命令,该命令对表变量中的所有值使用IN操作。 ...

...或者您可以将XML发送到您的过程并使用FOR XML操作来执行类似操作(即将XML解析为表变量等等。

无论哪种方式,您都需要以类似于表格的数据而不是以逗号分隔的字符串结束。

答案 3 :(得分:0)

看起来像SQL Server代码。如果是这样,这是一个将分隔列表转换为表格的UDF:

Create Function [dbo].[ParseTextString] (@S Text, @delim VarChar(5))
Returns @tOut Table 
    (ValNum Integer Identity Primary Key, 
     sVal VarChar(8000))
As
Begin 
Declare @dLLen TinyInt        -- Length of delimiter
Declare @sWin  VarChar(8000)  -- Will Contain Window into text string
Declare @wLen  Integer        -- Length of Window
Declare @wLast TinyInt        -- Boolean to indicate processing Last Window
Declare @wPos  Integer        -- Start Position of Window within Text String
Declare @sVal  VarChar(8000)  -- String Data to insert into output Table
Declare @BtchSiz Integer      -- Maximum Size of Window
     Set @BtchSiz = 7900      -- (Reset to smaller values to test routine)
Declare @dPos Integer         -- Position within Window of next Delimiter
Declare @Strt Integer         -- Start Position of each data value within Window
-- -------------------------------------------------------------------------

    -- Default delimiter is pipe char -----
    If @delim is Null Set @delim = '|' 
    If DataLength(@S) = 0 Or
        Substring(@S, 1, @BtchSiz) = @delim Return
    -- ---------------------------
    Select @dLLen = Len(@delim),
        @Strt = 1, @wPos = 1,
        @sWin = Substring(@S, 1, @BtchSiz)
    Select @wLen = Len(@sWin),
        @wLast = Case When Len(@sWin) = @BtchSiz
            Then 0 Else 1 End,
         @dPos = CharIndex(@delim, @sWin, @Strt)
    -- ----------------------------
    While @Strt <= @wLen
    Begin
         If @dPos = 0 -- No More delimiters in window
         Begin    
             If @wLast = 1 Set @dPos = @wLen + 1 
             Begin
                  Set @wPos = @wPos + @Strt - 1
                  Set @sWin = Substring(@S, @wPos, @BtchSiz)
                  -- ----------------------------------------
                  Select @wLen = Len(@sWin), @Strt = 1,
                        @wLast = Case When Len(@sWin) = @BtchSiz
                                  Then 0 Else 1 End,
                         @dPos = CharIndex(@delim, @sWin, 1)
                  If @dPos = 0 Set @dPos = @wLen + 1 
             End
        End
        -- -------------------------------
        Set @sVal = LTrim(Substring(@sWin, @Strt, @dPos - @Strt))
        Insert @tOut (sVal) Values (@sVal)
        -- -------------------------------
        -- Move @Strt to char after last delimiter
         Set @Strt = @dPos + @dLLen 
         Set @dPos = CharIndex(@delim, @sWin, @Strt)
     End
   Return 
 End

答案 4 :(得分:0)

我通常会将CSV转换为表格。但是,另一种简单的方法是构建一个字符串和exec或sp_executesql字符串。这有一些安全隐患。您可能需要以不同方式管理权限,因为调用者需要具有执行存储过程的权限以及从表中删除的权限。

DECLARE @sql varchar(max)

SELECT @sql ='DELETE FROM tbl_ItemFoldersLnk WHERE LineItemID IN('+ @sql +')'

EXEC(@sql)