首页 > 解决方案 > 批量删除操作程序不起作用

问题描述

我有一个如下所示的存储过程:

alter procedure [dbo].[zsp_deleteEndedItems]
(
@ItemIDList nvarchar(max)
)
as
delete from 
SearchedUserItems
WHERE EXISTS (SELECT 1 FROM dbo.SplitStringProduction(@ItemIDList,',') S1 WHERE ItemID=S1.val)

参数 IDList 传递如下:

124125125,125125125...etc etc

拆分字符串函数如下所示:

ALTER FUNCTION [dbo].[SplitStringProduction]
(
  @string nvarchar(max),
  @delimiter nvarchar(5)
) RETURNS @t TABLE
(
  val nvarchar(500)
)
AS
BEGIN
  declare @xml xml
  set @xml = N'<root><r>' + replace(@string,@delimiter,'</r><r>') + '</r></root>'

  insert into @t(val)
  select 
    r.value('.','varchar(500)') as item
  from @xml.nodes('//root/r') as records(r)

  RETURN
END

这应该从 ID 下的“SearcheduserItems”表中删除所有项目:

124125125 and 125125125

但是由于某种原因,在我进行了选择以查看它之后:

select * from SearchedUserItems
where itemid in('124125125','125125125')

记录还在...

我在这里做错了什么?有人可以帮我吗?

标签: c#sqlasp.netsql-serverstored-procedures

解决方案


如评论中所述,另一种选择是使用表类型参数。然而,这做出了一些假设(一些评论),应该让你走上正确的道路:

CREATE TYPE dbo.IDList AS TABLE (ItemID int NOT NULL); --Assumed int datatype;
GO

ALTER PROC dbo.zsp_deleteEndedItems @ItemIDList dbo.IDList READONLY AS

    DELETE SUI
    FROM dbo.SearchedUserItems SUI
         JOIN @ItemIDList IDL ON SUI.ItemID = IDL.ItemID;
GO

--Example of usage

DECLARE @ItemList dbo.IDList;

INSERT INTO @ItemList
VALUES(123456),(123457),(123458);

EXEC dbo.zsp_deleteEndedItems @ItemList;

GO

关于内联表值函数的问题,下面是一个这样的例子,我很快写了出来,它提供了一个包含接下来 1000 个数字的计数表:

CREATE FUNCTION dbo.NextThousand (@Start int)
RETURNS TABLE
AS RETURN

    WITH N AS(
        SELECT N
        FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)
    )
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 + @Start AS I
    FROM N N1 --10
         CROSS JOIN N N2 --100
         CROSS JOIN N N3; --1,000
GO

iTVF 的重要之处在于它只有一个语句,那就是RETURN语句。将表声明为返回类型变量,将数据插入其中,并返回该变量将其变为多行 TVF;执行速度要慢得多。


推荐阅读