繁体   English   中英

在SQL Server中特别是在SQL Server 2005中更新了SQL Server中的值

[英]Updated Value in SQL Server specially in SQL server 2005

如何在SQL Server 2005中专门在触发器中检测更新的值?

IF UPDATE (mycol1) 

例如

CREATE TRIGGER reminder
ON Person.Address
AFTER UPDATE 
AS 
IF ( UPDATE (StateProvinceID) OR UPDATE (PostalCode) )
BEGIN
    RAISERROR (50009, 16, 10)
END;
GO

参考

如果您引用的是实际值,这些值将保留在inserteddeleted表中。 请参阅使用插入和删除的表

请注意,您不应尝试获取该值,因为应将触发器编码为处理多个行更改

也就是说,您可以使用特殊的DELETED和INSERTED表

CREATE TRIGGER TRG_SomeTable_U ON dbo.SomeTable AFTER UPDATE 
AS 

-- DECLARE @ TABLE ...
-- INSERT HistoryTable
-- whatever

SELECT
    ...
FROM
   INSERTED I
   JOIN
   UPDATED U ON I.PK 0 U.PK
WHERE
  I.SomeColumn <> U.SomeColumn -- does not handle NULLs
GO

最简单的解决方案使用触发器。 看一下他的例子。 也许会帮助您。 另外,您可以在源代码中找到一些注释。

--Test initialization
CREATE TABLE dbo.[Transaction]
(
    ID INT IDENTITY(1,1) PRIMARY KEY,
    InsertDateTime DATETIME NOT NULL DEFAULT GETDATE(),
    [Date] DATETIME,
    CustomerID VARCHAR(50),
    [Type] VARCHAR(3),
    Amount MONEY
);
GO

INSERT INTO [Transaction]([Date],CustomerID,[Type],Amount)
SELECT '2011-01-01','CUST1001','INV','12,000' UNION ALL
SELECT '2011-01-02','CUST1001','PAY','3,000' UNION ALL
SELECT '2011-01-03','CUST1001','INV','8,000' UNION ALL
SELECT '2011-01-04','CUST1001','PAY','9,000' UNION ALL
SELECT '2011-01-04','CUST1002','INV','1,000' UNION ALL
SELECT '2011-01-05','CUST1002','PAY','5,000' UNION ALL
SELECT '2011-01-05','CUST1002','INV','6,000';
GO

CREATE TABLE AuditTransaction
(
     AuditID INT IDENTITY(1,1) PRIMARY KEY
    ,UpdateDateTime DATETIME NOT NULL DEFAULT GETDATE()
    ,ID INT NOT NULL
    ,[Date] DATETIME NULL
    ,CustomerID VARCHAR(50) NULL
    ,[Type] VARCHAR(3) NULL
    ,Amount MONEY NULL
);
GO

CREATE TRIGGER trgI_Transaction_Logging
ON dbo.[Transaction]
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;
    --Will be inserted only the old values (d.* = deleted.*) . Otherwise NULL will be inserted.
    INSERT  dbo.AuditTransaction(ID,[Date],CustomerID,[Type],Amount)
    SELECT  i.ID
            --If the old value (d.[Date]) and the new one (i.[Date]) are both equals 
            --then "NULL" 
            --else "old value" (d.[Date])
            ,NULLIF(d.[Date],i.[Date])
            ,NULLIF(d.CustomerID,i.CustomerID)
            ,NULLIF(d.[Type],i.[Type])
            ,NULLIF(d.Amount,i.Amount)
    FROM    deleted d INNER JOIN inserted i ON d.ID=i.ID;
END;
GO
--End of Test initialization

--Test: run UPDATEs
WAITFOR DELAY '00:00:01'; 
UPDATE  dbo.[Transaction] 
SET     Amount = Amount + 5
WHERE   ID = 1;
--1 second delay between UPDATEs
WAITFOR DELAY '00:00:01'; 
UPDATE  dbo.[Transaction] 
SET     Amount = Amount + 9
        ,[Date] = '2011-01-02 22:22:22'
WHERE   ID = 2;
WAITFOR DELAY '00:00:01';
UPDATE  dbo.[Transaction] 
SET     Amount = Amount + 9
        ,[Date] = '2011-01-02 11:11:11'
WHERE   ID = 1;
WAITFOR DELAY '00:00:01';
UPDATE  dbo.[Transaction] 
SET     Amount = Amount + 10
WHERE   ID = 3;
WAITFOR DELAY '00:00:01';
UPDATE  dbo.[Transaction] 
SET     Amount = Amount + 20
WHERE   ID = 4;
WAITFOR DELAY '00:00:01';
UPDATE  dbo.[Transaction] 
SET     CustomerID = NULL
WHERE   ID = 5;
--End of UPDATEs

PRINT 'dbo.AuditTransaction content'
SELECT  *
FROM    dbo.AuditTransaction at;

--Test: checking ”log” (audit table) for the first transaction
DECLARE @TransactioID INT;
SELECT  @TransactioID = 1;
PRINT 'Transaction 1 history'
SELECT  'I' AS OperationType, t.[InsertDateTime] OperationDateTime, 0 AS AuditID
        ,t.ID, t.[Date], t.CustomerID, t.[Type], t.Amount
FROM    dbo.[Transaction] t
WHERE   t.ID = @TransactioID 
UNION ALL
SELECT  'U' AS OperationType, at.UpdateDateTime, at.AuditID
        ,at.ID, at.[Date], at.CustomerID, at.[Type], at.Amount
FROM    dbo.AuditTransaction at
WHERE   at.ID = @TransactioID 
ORDER BY OperationType DESC, OperationDateTime;
--End of test

--By, by
DROP TABLE dbo.AuditTransaction;
DROP TABLE dbo.[Transaction];
GO

结果:

dbo.AuditTransaction content
AuditID     UpdateDateTime          ID          Date                    CustomerID                                         Type Amount
----------- ----------------------- ----------- ----------------------- -------------------------------------------------- ---- ---------------------
1           2011-10-02 13:48:22.683 1           NULL                    NULL                                               NULL 12000,00
2           2011-10-02 13:48:23.677 2           2011-01-02 00:00:00.000 NULL                                               NULL 3000,00
3           2011-10-02 13:48:24.680 1           2011-01-01 00:00:00.000 NULL                                               NULL 12005,00
4           2011-10-02 13:48:25.680 3           NULL                    NULL                                               NULL 8000,00
5           2011-10-02 13:48:26.683 4           NULL                    NULL                                               NULL 9000,00
6           2011-10-02 13:48:27.683 5           NULL                    CUST1002                                           NULL NULL

(6 row(s) affected)

Transaction 1 history
OperationType OperationDateTime       AuditID     ID          Date                    CustomerID                                         Type Amount
------------- ----------------------- ----------- ----------- ----------------------- -------------------------------------------------- ---- ---------------------
U             2011-10-02 13:56:41.420 1           1           NULL                    NULL                                               NULL 12000,00
U             2011-10-02 13:56:43.430 3           1           2011-01-01 00:00:00.000 NULL                                               NULL 12005,00
I             2011-10-02 13:56:40.363 0           1           2011-01-02 11:11:11.000 CUST1001                                           INV  12014,00

(3 row(s) affected)

如何解释这些结果? “ I”行包含实际值,而“ U”行包含旧值。

例:

  1. 对于Amount字段,第一个值为12014,最后一个值为12014。
  2. CustomerID字段未修改。
  3. [Date]字段从2011-10-02 13:56:43.430 2011-01-01 00:00:00.000修改为2011年1 2011-10-02 13:56:43.430 2011-01-02 11:11:11.000

我发现这个答案是正确的! 对表进行更新后,将使用UPDATE触发器来执行操作。

CREATE TRIGGER tr_Orders_UPDATE
ON Orders
AFTER UPDATE
AS

--Make sure Priority was changed
IF NOT UPDATE(Ord_Priority)
RETURN

--Determine if Priority was changed to high
IF EXISTS (SELECT *
       FROM INSERTED a
   JOIN DELETED b ON a.Ord_ID=b.Ord_ID
   WHERE b.Ord_Priority <> 'High' AND
   a.Ord_Priority = 'High')
BEGIN
DECLARE @Count tinyint
SET @Count = (SELECT COUNT(*)
            FROM INSERTED a
    JOIN DELETED b ON a.Ord_ID=b.Ord_ID
    WHERE b.Ord_Priority <> 'High' AND
    a.Ord_Priority = 'High')
PRINT CAST(@Count as varchar(3))+' row(s) where changed to a priority of High'
END
go

在第一部分中,INSERT触发器监视优先级为“高”的订单。 UPDATE触发器监视优先级从其他更改为“高”的订单。

IF语句检查以查看Ord_Priority值是否已更改。 如果没有,我们可以通过立即退出触发器来节省一些时间。

删除的表包含更新前的值,插入的表包含新值。 将表连接在一起后,很容易知道优先级何时从其他更改为“高”。

参考

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM