【问题标题】:SQL Server delete trigger returns select statement, how to capture that data?SQL Server 删除触发器返回选择语句,如何捕获该数据?
【发布时间】:2015-02-19 18:40:53
【问题描述】:

在一个表上,有一个删除触发器执行一些操作,然后在最后执行一个 select 语句,所以当你执行类似的操作时......

delete from mytable where id=1

它返回一个记录集。

有没有办法将该记录集的结果保存到临时表或其他东西中?我尝试过这样的事情:

declare @temptable table (returnvalue int);
insert into @temptable (returnvalue)
delete from mytable where id=1;

但显然这种语法不起作用。

【问题讨论】:

  • 您可以将结果保存到真实表格中。但是您必须在触发代码中执行此操作。不在执行删除的代码中。
  • 顺便说一句(因为此代码可能不受您的控制),让DELETE 触发器返回结果集是一个糟糕的主意。除了令人惊讶之外,它还使得将DELETE 作为必须返回其自己的结果集的多语句代码的一部分发出是不可能的。如果您想将结果作为删除的一部分,请使用OUTPUT clause
  • 为什么?您真正的问题以及您的问题应该解决的问题是您这样做的原因。触发器的结果集是一件非常奇怪的事情,修复该设计缺陷应该是您的目标。您从删除触发器返回结果集的动机可能是什么?

标签: sql-server triggers sql-server-2012


【解决方案1】:

嗯,

我无法想象您需要使用触发器返回记录集来返回您将删除的行的记录集的情况。但我不是来评判你的要求的。

好吧,您可以使用 OUTPUT 来显示将被排除的行数据并将这些数据输入到临时表中。请按照以下示例进行操作。

但是您应该知道:SQL Server 不保证使用 OUTPUT 子句的 DML 语句处理和返回行的顺序。由应用程序决定是否包含一个 WHERE 子句 适当的 que 可以保证 Desired 语义,或者 理解 que 当多行可能符合 DML 操作的条件时,保证顺序。下面的示例使用子查询,并且您假设唯一性是列的一个特征,以便将 DatabaseLogID 放置在所需的排序语义中。请参阅link

例子:

CREATE TABLE Person
(
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
GO

--DECLARE @MyTablePerson TABLE
--(
--    PersonID int,
--    LastName varchar(255),
--    FirstName varchar(255)
--);
--GO

--CREATE TRIGGER TRG_DLT_Person
--ON Person
--INSTEAD OF DELETE
--AS
--BEGIN

     -- Some code you want to do before delete

--     DELETE Person
--     FROM DELETED D
--END
--GO

insert into Person
(PersonID,
LastName,
FirstName)
values
(1,
'Kilmister',
'Lemmy');
GO

insert into Person
(PersonID,
LastName,
FirstName)
values
(2,
'Gilmour',
'David');
GO

insert into Person
(PersonID,
LastName,
FirstName)
values
(3,
'Rose',
'Axl');
GO

insert into Person
(PersonID,
LastName,
FirstName)
values
(4,
'Bullock',
'Sandra');
GO

--

select * from Person;
GO

delete from Person
--output deleted.* INTO @MyTablePerson
output deleted.*
WHERE PersonID = 4 OR PersonID = 2;
GO

select * from Person;
GO

select * from @MyTablePerson;
GO

我把我展示的例子放在了这个环境中,但是在这个环境中相信临时表不支持。

SQL Fiddle

【讨论】:

    【解决方案2】:

    尽管这是一种不好的做法,因为任何与表格交互的人都很难知道它会发生并在它发生时处理它,并且无论它是否可以捕获,一个非常充分的理由 not 从触发器返回结果集的原因是,从 SQL Server 的下一版本之一开始不允许这样做,因此无论如何您都必须重新编码该功能。 disallow results from triggers Server Configuration Option 的 MSDN 页面指出:

    重要

    此功能将在 Microsoft SQL Server 的下一版本中删除。不要在新的开发工作中使用此功能,并尽快修改当前使用此功能的应用程序。我们建议您将此值设置为 1。

    如果您只是从触发器返回类似SELECT IdField FROM deleted; 的内容,那么您应该(嗯,真的需要)改用OUTPUT 子句。

    话虽如此,执行以下操作将满足您的需求:

    CREATE TABLE #TempResults
    (
      ReturnValue INT
    );
    
    INSERT INTO #TempResults (ReturnValue)
      EXEC('DELETE FROM mytable WHERE id = 1;');
    

    您可以使用以下方法进行测试:

    SET NOCOUNT ON;
    IF (OBJECT_ID('dbo.DeleteTriggerWithResults') IS NOT NULL)
    BEGIN
      DROP TABLE dbo.DeleteTriggerWithResults;
    END;
    
    CREATE TABLE dbo.DeleteTriggerWithResults
    (
      Col1 INT NOT NULL IDENTITY(1, 1),
      Col2 DATETIME DEFAULT (GETDATE())
    );
    GO
    CREATE TRIGGER dbo.tr_DeleteTriggerWithResults_d
    ON dbo.DeleteTriggerWithResults
    AFTER DELETE
    AS
    BEGIN
    
      SELECT Col1
      FROM deleted;
    
    END;
    GO
    
    INSERT INTO dbo.DeleteTriggerWithResults DEFAULT VALUES;
    GO 30
    
    SELECT * FROM dbo.DeleteTriggerWithResults;
    

    然后运行测试:

    DECLARE @TempResults TABLE (Col1 INT);
    
    INSERT INTO @TempResults (Col1)
    EXEC('
        DELETE TOP (10)
        FROM  dbo.DeleteTriggerWithResults;
    ');
    
    SELECT * FROM @TempResults;
    

    返回:

    Col1
    --------
    10
    9
    8
    7
    6
    5
    4
    3
    2
    1

    【讨论】:

    • 好吧,为了完整起见,我不得不提一下,“这个特性将被删除”免责声明往往会在 SQL 中徘徊多年,然后才会删除一个特性——如果有的话。以防万一:此特定功能自 2008 年以来已弃用,但截至 SQL Server 2014 仍未删除。TEXTNTEXTIMAGE 已弃用十年,但仍然可用。他们应该在该消息中将“will”替换为“might”...
    • @JeroenMostert 是的,但截至 2005 年,它并未被指出已弃用,因此已宣布其意图。我知道他们有时会让这些事情流连忘返,这就是为什么我在接下来的几个版本中而不是下一个版本中说。此外,如果您查看 Deprecated Database Engine Features 页面,它在 2008 R2 之前被列为 在未来版本中不受支持,然后在 2008 R2 之前被列为 在下一个版本中不受支持 2012 年。所以他们离实现这一目标越来越近了。
    猜你喜欢
    • 1970-01-01
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多