删除一些条目和 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, ',');
希望对您有所帮助。
我想创建一个存储过程或数据库函数来删除一些条目和 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, ',');
希望对您有所帮助。