删除一些条目和 return 它们的 ID 的存储过程

Stored procedure to delete some entries and return their IDs

我想创建一个存储过程或数据库函数来删除一些条目和 return 它们的 ID 给客户端。我从这个开始 FUNCTION:

CREATE FUNCTION dbo.FixHangingCarriers ()
RETURNS @returntable TABLE
(
    ID_Plant INT NOT NULL,
    ID_ChargeCarrier INT NOT NULL
)
AS
BEGIN;
    -- Declare a temporary table
    DECLARE @EntriesToDelete TABLE (
        ID_ChargeCarrier INT NOT NULL,
        ID_Storage INT NOT NULL,
        StoredOn DATETIME2(2) NOT NULL
    );

    -- Select all the entries that should be deleted
    INSERT INTO @EntriesToDelete
    SELECT
        ID_ChargeCarrier,
        ID_Storage,
        StoredOn
    FROM dbo.CurrentStorage
    WHERE ID_StorageType = 4
    AND StoredOn < DATEADD(MINUTE, -30, GetDate());

    -- Return immediately, if there is currently nothing to delete
    IF (SELECT 1 FROM @EntriesToDelete) = 1
        RETURN;

    -- Delete hanging entries
    DELETE ccs
    FROM dbo.ChargeCarrier_Storage ccs
    INNER JOIN @EntriesToDelete d ON
        d.ID_ChargeCarrier = ccs.ID_ChargeCarrier AND
        d.ID_Storage = ccs.ID_Storage AND
        d.StoredOn = ccs.StoredOn;

    -- Prepare return table
    INSERT INTO @returntable
    SELECT cs.ID
    FROM @EntriesToDelete d
    INNER JOIN dbo.ChargeCarriersCurrentlyInPlant cp ON
        cp.ID_ChargeCarrier = d.ID_ChargeCarrier;

    -- Return deleted entries to caller
    RETURN;
END;

显然这是行不通的,因为 SQL 函数不能删除任何东西。本来想把它改成PROCEDURE,后来一看,那个程序自然好象不能return改成table。我该如何解决这个问题?

正如评论所暗示的那样,这似乎是您所需要的:

CREATE PROC dbo.FixHangingCarriers 
AS BEGIN

    DELETE ccs
    OUTPUT deleted.ID
    FROM dbo.ChargeCarrier_Storage ccs
         INNER JOIN CurrentStorage cs ON cs.ID_ChargeCarrier = ccs.ID_ChargeCarrier
                                     AND cs.ID_Storage = ccs.ID_Storage
                                     AND cs.StoredOn = ccs.StoredOn
    WHERE cs.ID_StorageType = 4
      AND cs.StoredOn < DATEADD(MINUTE, -30, GETDATE());
END;

你基本上有两个选择。

一种是按照建议将行 return 作为 SELECT 语句的一部分。但是,如果您想在 T-SQL 的下一位中使用它们,则不能仅通过存储过程从 table return 中获取 SELECT。

很多人要求像 SELECT * FROM (EXEC someproc) 这样的命令,但它不存在。

你可以做的是像这样定义一个 table 变量:

DECLARE @OutputIDs TABLE
(
    OutputIDKey int IDENTITY(1,1) PRIMARY KEY,
    OutputID int
);

然后您可以使用 INSERT EXEC 获取值:

INSERT @OutputIDs (OutputID)
EXEC dbo.MyStoredProcedure;

然后您可以在 table 变量中使用 ID 来执行您想要的操作。 (注意:您也可以使用临时 table 来做到这一点,但这并不是一个好的选择)

另一种选择是对存储过程使用 OUTPUT 参数。但是,在 return 之前,您需要将所有 ID 打包成一个字符串(可能是 comma-delimited 列表)。然后,您使用一个函数将字符串解压缩回一组 ID。 (如果您使用的是 SQL Server 2016 或更高版本,则可以使用 STRING_SPLIT 函数)。

使用 OUTPUT 参数的诀窍在于,您必须在调用过程时以及在过程本身的 header 中将其定义为 OUTPUT。这是框架代码:

CREATE PROCEDURE dbo.DoSomething
@OtherParameter int,
@IDsToOutput nvarchar(max) OUTPUT,
@YetAnotherParameter int
AS
BEGIN
...
END;

然后当你调用过程时,你这样做:

DECLARE @OutputIDs nvarchar(max);

EXEC dbo.DoSomething @OtherParameter = 1, 
                     @IDsToOutput = @OutputIDs OUTPUT,
                     @YetAnotherParameter = 2;

SELECT * FROM STRING_SPLIT(@OutputIDs, ',');

希望对您有所帮助。