2009-11-13 20 views
0

我创建了一个存储过程通过接受以逗号分隔的ID列表为varchar,并使用试图删除删除多条记录 - 不工作:SPROC用逗号分隔的输入删除多行?

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时出错。”

我有,通过逗号分隔的清单,我可以用它来删除重复其他存储过程,但后来我跑的每一行删除功能。

对此提出建议?

谢谢。

回答

1

Arrays and lists in SQL Server

您需要更改CSV为表(按条),并加入过滤。

您是从字面上比较ID列以字符串“1,45,67”,这不是整数...

0

你可以解析输入字符串转换成离散值(由例如用户defined-功能),将这些值转换为表格对象,然后发出使用针对您的表变量的所有值运行中的删除命令....

...或者你可以发送XML到你的程序和使用在FOR XML操做类似(即解析XML到一个表变量etc.etc。

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

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 
+0

迪尔我。你在这里看到过更简单的代码和技术:http://www.sommarskog.se/arrays-in-sql-2005.html – gbn 2009-11-13 20:32:31

+0

@gbn,可处理任何大小(> 8k字节)的输入字符串,以及任意多字符分隔符......前段时间我需要一个演出的thios,并将它保留为我的标准分隔字符串分析器,因为... – 2009-11-13 20:42:44

1

假设字符串是一个逗号分隔的整数值的清单,试试这个:

SET @ ItemsList =“” +替换(@ItemsList,'','')+','

现在,列表中应该有每个数字都用逗号和多余空格分隔。对于删除的查询变得

DELETE FROM tbl_ItemFoldersLnk WHERE CHARINDEX( ' '+ LTRIM(STR(LineItemID))+',',@ ITEMLIST)> 0

性能不会很大,但它会完成这项工作...

0

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

DECLARE @sql VARCHAR(最大)

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

EXEC(@sql)