简体   繁体   English

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

[英]SPROC to delete multiple rows with comma-delimited input?

I've created a sproc to delete multiple records by accepting a comma-delimited list of ID's as varchar, and using IN to attempt the deletion - doesn't work: 我通过接受以逗号分隔的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

Initially I had ... IN (@ItemList) but still does not work. 最初我有... IN(@ItemList),但仍然无法正常工作。 The error is "Error converting data type varchar to bigint." 错误为“将数据类型varchar转换为bigint时出错”。

I do have other SPROCS that iterate through comma delimited lists which I could use to delete, but then I'm running a delete function for each row. 我确实有其他SPROCS可以通过逗号分隔的列表进行迭代,我可以使用这些列表进行删除,但是随后我为每行运行一个删除功能。

Suggestions? 建议?

Thanks. 谢谢。

Arrays and lists in SQL Server . SQL Server中的数组和列表

You need to change the CSV into a table (as per article) and join to filter. 您需要将CSV更改为表格(根据文章),然后加入以进行过滤。

You are literally comparing the ID columns with the string "1, 45, 67" which is not an integer... 您实际上是在将ID列与字符串“ 1、45、67”(不是整数)进行比较。

Assuming the string is a comma delimited list of integer values, try this: 假设该字符串是逗号分隔的整数值列表,请尝试以下操作:

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

Now the list should have every number delimited by a comma and extra spaces removed. 现在,列表中应该用逗号分隔每个数字,并删除多余的空格。 The query for the delete becomes 查询删除成为

DELETE FROM tbl_ItemFoldersLnk WHERE Charindex(','+ltrim(str(LineItemID))+',',@ItemList) > 0 从tbl_ItemFoldersLnk删除Charindex(','+ ltrim(str(LineItemID))+',',@ ItemList)> 0

Performance will not be great, but it will get the job done... 性能不会很好,但是可以完成工作...

You could parse the input string into discrete values (by eg a user-defined-function), inserting these values into a table object, and then issuing a delete command that uses the IN operation against all values in your table variable.... 您可以将输入字符串解析为离散值(例如,通过用户定义的函数),将这些值插入表对象中,然后发出删除命令,该命令对表变量中的所有值使用IN操作。

...or you could send XML to your procedure and use the FOR XML operation to do similar (ie parse the XML into a table variable etc.etc. ...或者您可以将XML发送到过程中,并使用FOR XML操作执行类似操作(即,将XML解析为表变量等。

Either way, you'll need to end up with table-like data rather than a comma-delimited string. 无论哪种方式,您都需要以类似于表格的数据结尾,而不是以逗号分隔的字符串结尾。

Looks like SQL Server code. 看起来像SQL Server代码。 If so, Here's a UDF to convert a delimited list into a table: 如果是这样,请使用以下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

I typically convert the CSV into a table. 我通常将CSV转换为表格。 However, another simple way to do this is to build a string and exec or sp_executesql the string. 但是,另一种简单的方法是构建一个字符串,然后执行exec或sp_executesql字符串。 This has some security implications. 这有一些安全隐患。 You may need to manage permissions differently because the caller will need permission to exec the stored proc as well as permission to delete from the table. 您可能需要以不同的方式管理权限,因为调用方将需要执行存储的proc的权限以及从表中删除的权限。

DECLARE @sql varchar(max) 十进制@sql varchar(max)

SELECT @sql = 'DELETE FROM tbl_ItemFoldersLnk WHERE LineItemID IN (' + @sql + ')' SELECT @sql ='从tbl_ItemFoldersLnk中删除LineItemID IN('+ @sql +')'

exec(@sql) EXEC(@sql)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM