介绍 (Introduction)

Audit tables are used to track transactions for a particular table or tables. For every important transaction table, it’s important to create an audit table. Auditing can be helpful if you need to track who is Inserting/Updating and Deleting data on a sensitive table and/or view before and after data change information.

审计表用于跟踪一个或多个特定表的事务。 对于每个重要的事务表,创建审计表很重要。 如果您需要跟踪谁在敏感表上插入/更新和删除数据和/或在数据更改信息前后查看在监视敏感表上的数据,则审核可能会有所帮助。

Audit tables will have all the same columns of the audited table columns, in our example, along with who made the changes (user), when the change was made (date of transaction insert/update and delete), what data changed and the before and after views of changed data.

在我们的示例中,审核表将具有与审核表列相同的所有列,以及进行更改的用户(用户),进行更改的时间(事务插入/更新和删除的日期),更改的数据以及之前的内容。查看更改后的数据。

This article explains, step-by-step, how to set up an audit on an example Inventory table. We will create an inventory table, an audit table and triggers for inserting, updating, and deleting of inventory data. In our trigger, we will get all the Inventory transaction and store all the history information in an audit table.

本文分步说明了如何在示例库存表上设置审核。 我们将创建一个库存表,一个审计表以及用于插入,更新和删除库存数据的触发器。 在触发器中,我们将获取所有库存事务并将所有历史记录信息存储在审计表中。

This is a logic intensive “smart” audit that is going to shape our audit data and values, based on the transactions run against the inventory table and logic contained in the triggers. Therefore, there won’t be a one to one relationship between the number of transactions audited and records written to the audit log. The example illustrates the kind of logical processing that can be created within the auditing layer itself

这是一个逻辑密集的“智能”审计,它将根据针对库存表的交易和触发器中包含的逻辑来塑造我们的审计数据和价值。 因此,在审计的事务数量和写入审计日志的记录之间不会存在一对一的关系。 该示例说明了可以在审计层本身中创建的逻辑处理的种类

Step 1 Create Inventory Database: First, we will create an inventory database for our Inventory table, audit table and auditing Trigger for Insert/Update and delete.

步骤1创建库存数据库 :首先,我们将为库存表,审核表以及用于插入/更新和删除的审核触发器创建库存数据库。

 --Script to create DB, table, and sample Insert data
USE MASTER
GO-- 1) Check for the Database Exists .If the database is exist then drop and create new DB
IF not EXISTS (SELECT [name] FROM sys.databases WHERE [name] = 'InventoryDB' )
CREATE DATABASE InventoryDB
GOUSE InventoryDB
GO

Step 2 Create Inventory Table: Now we create our Inventory table

步骤2创建库存表 :现在,我们创建库存表

 USE InventoryDB
GO
IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'InventoryMasters' )
DROP TABLE InventoryMasters
GOCREATE TABLE [dbo].[InventoryMasters]([InventoryID] [int] IDENTITY(1,1) NOT NULL,ItemNO    varchar(10),InventoryDate Datetime null,InventorySeq int,InventoryType char(1),    Qty int
)

Here we can see Field used for Inventory Table

在这里我们可以看到用于库存表的字段

Inventory Table Filed Name Filed Details
InventoryID Identity Field
ItemNO Item No (This is for which item the inventory details are stored)
InventoryDate Inventory stock in/Out Date
InventorySeq Sequence Number for Inventory
InventoryType Inventory Type I/O (Inventory Item Quantity In/Inventory Item Quantity out
Qty In/Out Quantity
库存表文件名 归档的详细信息
库存ID 身份字段
编号 物料编号(这是存储库存明细的物料)
库存日期 库存进/出日期
库存序列 库存的序列号
库存类型 库存类型I / O(库存项目数量输入/库存项目数量输出
数量 进/出数量

Step 3 Create audit table: We need to create an audit table for storing our audit information. Here we create an audit table name with the name [Audit_InventoryMasters]

步骤3创建审核表 :我们需要创建一个审核表来存储我们的审核信息。 在这里,我们创建一个审计表名称,名称为[Audit_InventoryMasters]

 CREATE TABLE [dbo].[Audit_InventoryMasters]([Audit_InventoryID] [int] IDENTITY(1,1) NOT NULL,[InventoryID]  [int] ,ItemNO      varchar(10),RemainingQty  int,InQty     int,OutQty      int,ResultQty       int,AuditDate Datetime null,AuditbyUser   int,AuditType   char(1)   CONSTRAINT [PK_Audit_InventoryMasters] PRIMARY KEY CLUSTERED
([Audit_InventoryID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Here you can see each column on the [Audit_InventoryMasters] table and the purpose of the columns in detail.

在这里,您可以看到[Audit_InventoryMasters]表中的每一列以及这些列的详细信息。

Inventory Audit Filed Name Filed Details
Audit_InventoryID Identity Filed
InventoryID Inventory table Id
ItemNO Item No (This is for which item the inventory details are stored)
RemainingQty This is to store the previous date remaining Qty
InQty To store Inventory in Qty
OutQty To store Inventory out Qty
ResultQty This is Transaction result of every record – we will be using this formula to calculate our result quantity (RemainingQty+ InQty – OutQty)
AuditDate Inventory Type I/O (Inventory Item Quantity In/Inventory Item Quantity out
AuditbyUser In/Out Quantity
AuditType This is status character used to store what type of audit information is inserted like Insert/Update or Delete by (I/U or D)
库存审核文件名 归档的详细信息
Audit_InventoryID 身份证明
库存ID 库存表编号
编号 物料编号(这是存储库存明细的物料)
剩余数量 这是为了存储前一个日期剩余的数量
数量 以数量存储库存
数量 储存库存数量
结果数量 这是每条记录的交易结果–我们将使用此公式来计算结果数量(RemainingQty + InQty – OutQty)
审核日期 库存类型I / O(库存项目数量输入/库存项目数量输出
用户审核 进/出数量
审核类型 这是状态字符,用于存储插入了哪种类型的审核信息,例如“插入/更新”或“由( I / U或D )删除”

创建触发器 (Creating Triggers)

We have now created our tables for Inventory Management and auditing. Now we will see how to create Insert/Update/Delete Triggers for auditing transactions on our inventory table.

现在,我们已经创建了用于库存管理和审计的表。 现在,我们将看到如何在库存表上创建插入/更新/删除触发器以审计交易。

Step 4 Creating Insert Trigger:

步骤4创建插入触发器:

First, we will start with the Insert Trigger:

首先,我们将从插入触发器开始:

We have created an Insert Trigger named trInventoryInsert. This Insert Trigger is created to insert the IN/Out quantity of every transaction to the audit table. In this trigger, we have three conditions:

我们创建了一个名为trInventoryInsert的插入触发器。 创建此插入触发器的目的是将每笔交易的进/出数量插入到审计表中。 在此触发器中,我们具有三个条件:

  1. First, we check for the item already existing in the audit table. If not, then insert the In or Out Qty to the audit table. 首先,我们检查审核表中已经存在的项目。 如果不是,则将“入库数量”或“出库数量”插入审核表。
  2. If data exists, check for the Item available on the same date, then update the input and output Quantity and balance the resulting quantity with the logic implemented in the Insert Trigger. 如果存在数据,请检查同一日期的可用物料,然后更新输入和输出数量,并使用插入触发器中实现的逻辑来平衡所得数量。
  3. If the item is available but not for the selected date then insert a new record with In, out quantity and balance the result qty. 如果该物料可用,但不适用于所选日期,则插入一个新记录,输入进,出数量并平衡结果数量。
 USE InventoryDB
GO--Script to create DB, table, and sample INSERT datacreate TRIGGER trInventoryInsert ON [dbo].[InventoryMasters]
FOR INSERT
AS
BEGIN    SET NOCOUNT ON;declare @Count int=0;    declare @DateCount int=0;    declare @InventoryID int=0;   declare @InventoryDate datetime;    declare @InventorySeq int;    declare @InventoryType char(1);    declare @ItemNO varchar(10);    declare @Qty int;    declare @Result_Qty int=0;    declare @FinalInventoryType char(1);    declare @Unit_Qty int=0;    declare @New_QtyCheck int=0;    declare @New_OUT_QtyCheck int=0;     SELECT @InventoryID=i.InventoryID FROM inserted i;   SELECT @InventoryDate=i.InventoryDate FROM inserted i;      SELECT @InventorySeq=i.InventorySeq FROM inserted i;    SELECT @InventoryType=i.InventoryType FROM inserted i;    SELECT @ItemNO=i.ItemNO FROM inserted i;    SELECT @Qty=i.Qty FROM inserted i; SELECT @Count=COUNT(*) FROM Audit_InventoryMasters WHERE ItemNO=@ItemNO;    IF(@Count>0)    BEGIN    SELECT  @DateCount=COUNT(*)FROM Audit_InventoryMasters WHERE   ItemNO=@ItemNO     AND     AuditDate=@InventoryDateIF(@DateCount>0)     BEGIN    -- UPDATE AND loop for upadte all qty    SELECT top 1 @New_QtyCheck=InQty FROM     Audit_InventoryMasters     WHERE     ItemNO=@ItemNO AND     AuditDate=@InventoryDate SELECT top 1  @New_OUT_QtyCheck=OutQty FROM     Audit_InventoryMasters     WHERE     ItemNO=@ItemNO AND     AuditDate=@InventoryDate     IF(@InventoryType='I')    BEGIN             UPDATE Audit_InventoryMasters  SET   InQty=@Qty+@New_QtyCheck   WHERE     ItemNO=@ItemNO     AND     AuditDate=@InventoryDate  UPDATE Audit_InventoryMasters SET    RemainingQty=RemainingQty+@Qty  WHERE     ItemNO=@ItemNO     AND     AuditDate>@InventoryDate    UPDATE Audit_InventoryMasters SET  ResultQty=RemainingQty+InQty-OutQty    WHERE     ItemNO=@ItemNO     AND     AuditDate>=@InventoryDate    END    ELSE    BEGIN               UPDATE Audit_InventoryMasters SET OutQty=@Qty+@New_OUT_QtyCheck   WHERE     ItemNO=@ItemNO     AND     AuditDate=@InventoryDate    UPDATE Audit_InventoryMasters SET    RemainingQty=RemainingQty-@Qty  WHERE     ItemNO=@ItemNO     AND     AuditDate>@InventoryDate   UPDATE Audit_InventoryMastersSET ResultQty=RemainingQty+InQty-OutQty       WHERE     ItemNO=@ItemNO     AND     AuditDate>=@InventoryDate    END    END    ELSE    BEGIN   IF not exists (SELECT * FROM Audit_InventoryMasters WHERE AuditDate<@InventoryDate)BEGIN SET @Unit_Qty=0;-- SET @Result_Qty=0;ENDELSEBEGINSELECT top 1 @Unit_Qty=ResultQty FROM Audit_InventoryMasters WHERE ItemNO=@ItemNO AND AuditDate < @InventoryDate  --AND InventorySeq=@InventorySeq  order by AuditDate desc ENDIF(@InventoryType='I')    BEGIN    SET @Result_Qty=@Unit_Qty+@Qty    INSERT INTO Audit_InventoryMasters    (InventoryID,ItemNO,RemainingQty,InQty,OutQty,ResultQty,AuditDate,AuditbyUser,AuditType)     VALUES(@InventoryID,@ItemNO,@Unit_Qty,@Qty,0,@Result_Qty,@InventoryDate,101,'I');    UPDATE Audit_InventoryMastersSET    RemainingQty=RemainingQty+@Qty  WHERE     ItemNO=@ItemNO     AND     AuditDate>@InventoryDate    UPDATE Audit_InventoryMasters SET  ResultQty=RemainingQty+InQty-OutQty    WHERE     ItemNO=@ItemNO     AND     AuditDate>=@InventoryDate              END    ELSE    BEGIN    SET @Result_Qty=@Unit_Qty-@Qty   INSERT INTO Audit_InventoryMasters    (InventoryID,ItemNO,RemainingQty,InQty,OutQty,ResultQty,AuditDate,AuditbyUser,AuditType)     VALUES(@InventoryID,@ItemNO,@Unit_Qty,0,@Qty,@Result_Qty,@InventoryDate,101,'I');UPDATE Audit_InventoryMastersSET  RemainingQty=RemainingQty-@Qty  WHERE     ItemNO=@ItemNO     AND     AuditDate>@InventoryDate   UPDATE Audit_InventoryMasters SET    ResultQty=RemainingQty+InQty-OutQty    WHERE     ItemNO=@ItemNO     AND     AuditDate>=@InventoryDate    END            END END    ELSE    BEGIN      IF(@InventoryType='I')    BEGIN    INSERT INTO Audit_InventoryMasters    (InventoryID,ItemNO,RemainingQty,InQty,OutQty,ResultQty,AuditDate,AuditbyUser,AuditType)     VALUES(@InventoryID,@ItemNO,0,@Qty,0,@Qty,@InventoryDate,101,'I');    END    ELSE    BEGIN    INSERT INTO Audit_InventoryMasters    (InventoryID,ItemNO,RemainingQty,InQty,OutQty,ResultQty,AuditDate,AuditbyUser,AuditType)     VALUES(@InventoryID,@ItemNO,0,0,@Qty,-@Qty,@InventoryDate,101,'I');   END END
END 

插入库存数量检验 (Insert Test for Inventory Stock in Quantity )

Run the below insert script to test to see if our insert query is working for audit table insert.

运行以下插入脚本以测试我们的插入查询是否适用于审计表插入。


insert into InventoryMasters(ItemNO,InventoryDate,InventorySeq,InventoryType,Qty) values('I001','20161205',1,'I',100);insert into InventoryMasters
(ItemNO,InventoryDate,InventorySeq,InventoryType,Qty) values('I001','20161205',2,'I',40);

When we view result for both Inventory and audit table we can see 2 records will be inserted into the Inventory table with Quantity as 100 and 40. But for the audit table, we can see only one record inserted with the result as quantity as 140, which is an aggregate of the quantity for both transactions.

当我们查看库存和审核表的结果时,可以看到2条记录将被插入到库存表中,数量为100和40。但是对于审核表,我们只能看到一条记录,其结果为数量为140,这是两个交易的数量的总和。


select * from InventoryMasters
select * from Audit_InventoryMasters

插入库存缺货测试 (Insert Test for Inventory Stock out Quantity )

Run the below insert query to test our insert script is working for audit table for Out Quantity.

运行下面的插入查询以测试我们的插入脚本是否适用于缺货审核表。

 insert into InventoryMasters
(ItemNO,InventoryDate,InventorySeq,InventoryType,Qty) values('I001','20161205',2,'O',20);insert into InventoryMasters
(ItemNO,InventoryDate,InventorySeq,InventoryType,Qty) values('I001','20161205',2,'O',10);

When we view result for both Inventory and audit table we can see 4 records will be inserted into Inventory table with Stock in Quantity as 100 and 40 and Stock Out quantity as 20,10 with status as I, O. But for audit table we can see only one records inserted with result as quantity as 110 which is the sum of the quantity of all In transactions less the sum of all Out.

当我们查看库存和审计表的结果时,我们可以看到将有4条记录插入到库存表中,其中“存货数量”为100和40,“缺货数量”为20,10,状态为I,O。但是对于审计表,我们可以仅看到一条插入的记录,结果的数量为110,这是所有In事务的数量之和减去所有Out的总和。


select * from InventoryMasters
select * from Audit_InventoryMasters

不同日期的库存入库和出库: (Inventory Stock in and Stock out with different date:)

Now we can do few more insert tests with insert stock in and stock out quantity with the different date for the same item.

现在,我们可以对同一个商品使用不同日期的插入库存和库存数量进行更多的插入测试。

Here we do 2 insert for stock In for same different date for the same item and one more insert for Stock Out for same product and sequence no.

在这里,我们对同一商品在相同的不同日期进行了2次插入库存,对于相同产品和序列号又进行了一次库存插入。

 insert into InventoryMasters(ItemNO,InventoryDate,InventorySeq,InventoryType,Qty) values('I001','20161206',3,'I',70);insert into InventoryMasters
(ItemNO,InventoryDate,InventorySeq,InventoryType,Qty) values('I001','20161207',4,'I',30);
insert into InventoryMasters
(ItemNO,InventoryDate,InventorySeq,InventoryType,Qty) values('I001','20161207',4,'O',10);

When we view result for both Inventory and audit table we can see 4 records will be inserted into Inventory table with Stock in Quantity and Stock Out quantity for Item ‘I001’ and Inventory Date as ‘20161205, 20161206, 20161207’ with status as I, O. But for audit table we can see only three records inserted for dates ‘20161205, 20161206, 20161207’ with each day Remaining quantity, initially the remaining quantity is 0 and each day the remaining quantity was before day result quantity. In the resulting quantity, we have an actual result of stock quantity after Stock in and Stock out.

当我们同时查看库存表和审计表的结果时,我们会看到4条记录将被插入到库存表中,其中物料“ I001”的库存数量和缺货数量,库存日期为“ 20161205、20161206、20161207”,状态为I, O.但是对于审计表,我们只能看到在日期'20161205,20161206,20161207'中插入的三个记录,其中每天都有剩余数量,最初的剩余数量为0,而每天的剩余数量是当天结果数量之前。 在得出的数量中,我们得到库存进出后的实际数量。


select * from InventoryMasters
select * from Audit_InventoryMasters

Step 5 Creating Update Trigger:

步骤5创建更新触发器:

Next, we create our Audit Update Trigger:

接下来,我们创建审计更新触发器:

We have created an Update trigger named trInventoryUpdate.

我们创建了一个名为trInventoryUpdate的更新触发器。

Using this Update trigger each update on the Inventory Master table result will be updated to the audit table as a result.

使用此更新触发器,清单主表结果上的每个更新将作为结果更新到审核表。

  1. First, we check for the item already existing in the audit table. If exists update the input and output Quantity and update all Remaining and Result in the audit table. 首先,我们检查审核表中已经存在的项目。 如果存在,则更新输入和输出数量,并更新审核表中的所有剩余和结果。
  2. In some cases, the same product name with same date and different Seq. number will be updated. We have divided the Stock In Quantity update as based on Seq. number and based on product and date. 在某些情况下,相同的产品名称具有相同的日期和不同的序列号。 号码将被更新。 我们已根据顺序对“库存数量”更新进行了划分。 数字,并基于产品和日期。

The detailed Update trigger query is as follows:

详细的更新触发器查询如下:


USE inventoryDB
GO--Script to create DB,Table AND sample INSERT data
create TRIGGER trInventoryUpdate ON [dbo].[InventoryMasters]
FOR UPDATE
AS
BEGIN    SET NOCOUNT ON;           Declare @Count int=0;    Declare @DateCount int=0;  Declare @InventoryID int=0;   Declare @ROWINCOUNT int=0;   Declare @InventoryDate datetime;    Declare @InventorySeq int;    Declare @InventoryType char(1);    Declare @ItemNO varchar(10);    Declare @Qty int;    Declare @Result_Qty int=0;    Declare @FinalInventoryType char(1);    Declare @Unit_Qty int=0;    Declare @New_QtyCheck int=0;    Declare @New_OUT_QtyCheck int=0;  Declare @result_IN_Qty int=0;      Declare @result_OUT_Qty int=0; Declare @result_IN_Qty_CHK int=0;      Declare @result_IN_Qty_CHK_1 int=0;     Declare @result_OUT_Qty_CHK int=0; Declare @result_OUT_Qty_CHK_1 int=0; SELECT @InventoryID=i.InventoryID FROM inserted i;      SELECT @InventoryDate=i.InventoryDate FROM inserted i;      SELECT @InventorySeq=i.InventorySeq FROM inserted i;    SELECT @InventoryType=i.InventoryType FROM inserted i;    SELECT @ItemNO=i.ItemNO FROM inserted i;    SELECT @Qty=i.Qty FROM inserted i;      SELECT @DateCount=count(*) FROM Audit_InventoryMasters WHERE     ItemNO=@ItemNO     and     AuditDate=@InventoryDateIF(@DateCount>0)     BEGIN    -- UPDATE and loop for upadte all qty    SELECT top 1 @New_QtyCheck=InQty FROM     Audit_InventoryMasters     WHERE     ItemNO=@ItemNO and     AuditDate=@InventoryDate     SELECT top 1  @New_OUT_QtyCheck=OutQty  FROM     Audit_InventoryMasters     WHERE     ItemNO=@ItemNO and     AuditDate=@InventoryDate     SELECT @result_IN_Qty=sum(Qty) FROM InventoryMasters       WHERE     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='I'SELECT @result_OUT_Qty=sum(Qty) FROM InventoryMasters     WHERE     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='O'   IF(@InventoryType='I')    BEGIN    SELECT @result_IN_Qty_CHK=sum(InQty)FROM Audit_InventoryMastersWHEREItemNO=@ItemNO     and     AuditDate=@InventoryDate  UPDATE Audit_InventoryMasters SET InQty=@result_IN_Qty   WHERE     ItemNO=@ItemNO     and     AuditDate=@InventoryDate  SELECT @ROWINCOUNT=count(*) FROM InventoryMasters     WHERE     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='I'IF(@ROWINCOUNT>1)BEGINIF(@qty=0)BEGINUPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty-(@result_IN_Qty_CHK-@result_IN_Qty)  WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate ENDELSEBEGIN        IF(@result_IN_Qty_CHK>=@result_IN_Qty)BEGINSET @result_IN_Qty_CHK_1=@result_IN_Qty_CHK-@result_IN_Qty;UPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty-@result_IN_Qty_CHK_1WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate ENDELSEBEGINSET @result_IN_Qty_CHK_1=@result_IN_Qty-@result_IN_Qty_CHK;UPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty+@result_IN_Qty_CHK_1WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate ENDEND      ENDELSEBEGIN IF(@Qty>=@New_QtyCheck)    BEGINUPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty+(@Qty-@New_QtyCheck)  WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate   ENDELSEBEGINUPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty-(@New_QtyCheck-@Qty)  WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate   ENDENDUPDATE Audit_InventoryMasters SET ResultQty=RemainingQty+InQty-OutQty    WHERE     ItemNO=@ItemNO     and     AuditDate>=@InventoryDate    End    ELSE    BEGIN    SELECT @result_OUT_Qty_CHK=sum(OutQty)FROM Audit_InventoryMastersWHEREItemNO=@ItemNO     and     AuditDate=@InventoryDate UPDATE Audit_InventoryMasters SET OutQty=@result_OUT_Qty   WHERE     ItemNO=@ItemNO     and     AuditDate=@InventoryDate    SELECT @ROWINCOUNT=count(*) FROM InventoryMasters     WHERE     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='O'IF(@ROWINCOUNT>1)BEGINIF(@qty=0)BEGINUPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty+(@result_OUT_Qty_CHK-@result_OUT_Qty)  WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate ENDElseBEGIN        IF(@result_OUT_Qty_CHK>=@result_OUT_Qty)BEGINSET @result_OUT_Qty_CHK_1=@result_OUT_Qty_CHK-@result_OUT_Qty;UPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty+@result_OUT_Qty_CHK_1WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate ENDElseBEGINSET @result_OUT_Qty_CHK_1=@result_OUT_Qty-@result_OUT_Qty_CHK;UPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty+@result_OUT_Qty_CHK_1WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate ENDEND      ENDELSEBEGIN IF(@Qty>=@New_OUT_QtyCheck)    BEGINUPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty-(@Qty-@New_OUT_QtyCheck)  WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate   ENDELSEBEGINUPDATE Audit_InventoryMasters SET RemainingQty=RemainingQty+(@New_OUT_QtyCheck-@Qty)  WHERE     ItemNO=@ItemNO     and     AuditDate>@InventoryDate   ENDENDUPDATE Audit_InventoryMasters SET ResultQty=RemainingQty+InQty-OutQty    WHERE     ItemNO=@ItemNO     and     AuditDate>=@InventoryDate    End    END    END         

数量更新库存 (Update Test for Inventory Stock in Quantity )

Before the update, we can see the actual data of both Inventory and audit tables.

在更新之前,我们可以看到库存表和审计表的实际数据。

Now we are going to update Item No ‘I001’ for date ‘20161205’ and for InventorySeq no=3 with quantity as 120 now we can see the inserted original quantity is 40 from above result.

现在我们将更新日期为'20161205'的项目编号'I001',对于InventorySeq no = 3,数量为120,现在我们可以从上述结果中看到插入的原始数量为40。

Run the below update query to update quantity from 40 to 120

运行以下更新查询以将数量从40更新到120

 update InventoryMasters set Qty=120
whereInventoryDate='20161205'andItemNO='I001'andInventoryType='I'andInventorySeq=2

We can see both Inventory and audit table quantity information has been updated. In the audit table, we can see all Remaining Quantity and Result Quantity has been updated depend on new Stock Input Quantity update.

我们可以看到库存和审核表数量信息已更新。 在审核表中,我们可以看到所有剩余数量和结果数量已经更新,具体取决于新的库存输入数量更新。


select * from InventoryMasters
select * from Audit_InventoryMasters

库存缺货数量更新测试 (Update Test for Inventory Stock Out Quantity )

In the previous image, we can see InventoryID 3 and 4 the quantity has 20 and 10 as Stock Out. Now let’s update both this Stock Out Quantity as 0.

在上一个图像中,我们可以看到InventoryID 3和4,数量分别为20和10,作为缺货。 现在,我们将此缺货数量更新为0。

 update InventoryMasters set Qty=0
whereInventoryDate='20161205'andItemNO='I001'andInventoryType='O'andInventorySeq=2

We can see both Inventory and audit table quantity information has been updated. In the audit table, we can see all Remaining Quantity and Result Quantity has been updated depending on the new Stock output Quantity update.

我们可以看到库存和审核表数量信息已更新。 在审核表中,我们可以看到所有剩余数量和结果数量已更新,具体取决于新的库存输出数量更新。


select * from InventoryMasters
select * from Audit_InventoryMasters

Step 5 Creating Delete Trigger:

步骤5创建删除触发器:

Next, we create our Audit Update Trigger named as trInventoryDelete.

接下来,我们创建名为trInventoryDe​​lete的审计更新触发器。

  1. First, we check for the items already existing in the audit table. If exists, update the Input and Output quantity to 0 and result quantity, and update all remaining and Result quantity in the audit table. 首先,我们检查审核表中已经存在的项目。 如果存在,则将输入和输出数量更新为0和结果数量,并更新审核表中的所有剩余数量和结果数量。
  2. In some cases, the same product with the same date will have more than one row with different seq no. In that case, we need to minus the Stock In/Stock Out quantity with the same product with the deleted Seq. product qty. we have applied both the logic in the Delete trigger. 在某些情况下,具有相同日期的同一产品将有多于一行的不同序列号。 在这种情况下,我们需要减去带有已删除Seq的相同产品的库存/库存数量。 产品数量 我们已在Delete触发器中应用了这两种逻辑。

The detailed Delete Trigger query is as below:

详细的删除触发器查询如下:

 USE InventoryDB
GOcreate TRIGGER trInventoryDelete ON [dbo].[InventoryMasters]
FOR Delete
AS
BEGIN
SET NOCOUNT ON;    declare @Count int=0;
declare @DateCount int=0;  Declare @InventoryID int=0;
declare @ROWINCOUNT int=0;   Declare @InventoryDate datetime;    Declare @InventorySeq int;    Declare @InventoryType char(1);    Declare @ItemNO varchar(10);
declare @Qty int;
declare @Result_Qty int=0;    Declare @FinalInventoryType char(1);
declare @Unit_Qty int=0;
declare @New_QtyCheck int=0;
declare @New_OUT_QtyCheck int=0;
declare @result_IN_Qty int=0;
declare @result_OUT_Qty int=0;
declare @result_IN_Qty_CHK int=0;
declare @result_IN_Qty_CHK_1 int=0;
declare @result_OUT_Qty_CHK int=0;
declare @result_OUT_Qty_CHK_1 int=0; SELECT @InventoryID=d.InventoryID FROM deleted d;      SELECT @InventoryDate=d.InventoryDate FROM deleted d;      SELECT @InventorySeq=d.InventorySeq FROM deleted d;    SELECT @InventoryType=d.InventoryType FROM deleted d;    SELECT @ItemNO=d.ItemNO FROM deleted d;    SELECT @Qty=d.Qty FROM deleted d; select @DateCount=count(*) from Audit_InventoryMasters where
ItemNO=@ItemNO
and
AuditDate=@InventoryDateif(@DateCount>0)     BEGINif(@InventoryType='I')    Begin   select @ROWINCOUNT=count(*) from InventoryMasters     where     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='I'and InventorySeq=@InventorySeqif(@ROWINCOUNT<=0)BEGINselect @Qty=InQty-(select isnull(sum(Qty),0) from InventoryMasters     where     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='I')from Audit_InventoryMasters     where     ItemNO=@ItemNO and     AuditDate=@InventoryDateENDupdate Audit_InventoryMasters set InQty=InQty-@Qtywhere     ItemNO=@ItemNO     and     AuditDate=@InventoryDate      update Audit_InventoryMasters set RemainingQty=RemainingQty-@Qtywhere     ItemNO=@ItemNO     and     AuditDate>@InventoryDate update Audit_InventoryMasters set             ResultQty=RemainingQty+InQty-OutQty    where     ItemNO=@ItemNO     and     AuditDate>=@InventoryDate  ENDElseBEGINselect @ROWINCOUNT=count(*) from InventoryMasters     where     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='O'and InventorySeq=@InventorySeqif(@ROWINCOUNT<=0)BEGINselect @Qty=OutQty-(select isnull(sum(Qty),0) from InventoryMasters     where     ItemNO=@ItemNO and     InventoryDate=@InventoryDateand InventoryType='O')from Audit_InventoryMasters     where     ItemNO=@ItemNO and     AuditDate=@InventoryDateENDupdate Audit_InventoryMasters set OutQty=OutQty-@Qty               where     ItemNO=@ItemNO     and     AuditDate=@InventoryDate      update Audit_InventoryMasters set RemainingQty=RemainingQty+@Qtywhere     ItemNO=@ItemNO     and     AuditDate>@InventoryDate update Audit_InventoryMasters set             ResultQty=RemainingQty+InQty-OutQty    where     ItemNO=@ItemNO     and     AuditDate>=@InventoryDate  ENDEND
END

删除数量的库存库存测试 (Delete Test for Inventory Stock in Quantity )

Before the Delete, we can see the actual output of both Inventory and audit table.

在删除之前,我们可以看到库存和审核表的实际输出。

Now we are going to Delete Item No ‘I001’ for date ‘20161206’ and for InventorySeq no=3. Run the below update query to delete Stock In Quantity of 70 on 20161206’ for Item No ‘I001’

现在,我们要删除日期“ 20161206”和InventorySeq no = 3的项目编号“ I001”。 运行以下更新查询,以删除商品编号为“ I001”的“ 20161206上的库存70”

 DELETE FROM InventoryMasters WHEREInventoryDate='20161206'andItemNO='I001'andInventoryType='I'andInventorySeq=3

We can see the Item No’I001’ and Seq no of 3 for ‘20161206’ date Stock has been deleted from Inventory table and in the audit table, we can see the Stock In quantity has been updated to 0 and all Remaining Quantity and Result Quantity has been updated depend on new Stock Input Quantity delete.

我们可以看到“ 20161206”日期的项目编号“ I001”和编号为3的日期已从库存表中删除,并且在审计表中,我们可以看到库存数量已更新为0,并且所有剩余数量和结果数量已更新,具体取决于新的库存输入数量删除。


select * from InventoryMasters
select * from Audit_InventoryMasters

I hope you have enjoyed this article demonstrating a “smart” trigger based auditing layer and how this logic can be applied in a real world scenario

我希望您喜欢这篇文章,它演示了一个基于“智能”触发器的审计层,以及如何将此逻辑应用于现实世界中。

For a tool to create more generic trigger based audit trails automatically, see ApexSQL Trigger

有关自动创建更多基于通用触发器的审计跟踪的工具,请参阅ApexSQL触发器

有用的链接 (Useful links)

  • SQL Server Audit (Database Engine) SQL Server审核(数据库引擎)
  • Create Audit Table and Insert\Update\Delete Triggers for a given table 创建审计表并为给定表插入\更新\删除触发器
  • Track Data Changes (SQL Server) 跟踪数据更改(SQL Server)

翻译自: https://www.sqlshack.com/creating-smart-trigger-based-audit-trail-sql-server/

为SQL Server创建基于“智能”触发器的审核跟踪相关推荐

  1. SQL Server中的登录触发器概述

    This article gives you an overview of Logon triggers in SQL Server and its usage to control SQL Serv ...

  2. SQL SERVER 创建GHUID命令:select newid();

    SQL SERVER 创建GHUID命令:select newid(); insert into persion2(id,name,age) values(newid(),'j',23); 插入有中文 ...

  3. SQL server management 查询所有触发器

    SQL server management 查询所有触发器 SQL server management 查询所有触发器 SELECT OBJECT_NAME(a.parent_obj) AS [表名] ...

  4. SQL Server创建数据库和数据的增删改查

    SQL Server创建数据库和数据的增删改查 本文是针对数据的增删改查,数据的创建 首先我们使用命令创建sql server数据库 D盘新建一个文件夹DB use master go --创建数据库 ...

  5. SQL Server创建复合索引时,复合索引列顺序对查询的性能影响

    SQL Server创建复合索引时,复合索引列顺序对查询的性能影响 原文:SQL Server创建复合索引时,复合索引列顺序对查询的性能影响 说说复合索引 写索引的博客太多了,一直不想动手写,有一下两 ...

  6. Sql Server 创建临时表

    Sql Server 创建临时表 语法 创建临时表 方法一:create table #临时表名(字段1 约束条件,字段2 约束条件,.....)create table ##临时表名(字段1 约束条 ...

  7. SQL Server创建表语句介绍

    SQL Server创建表是最常见也是最常用的操作之一,下面就为您介绍SQL Server创建表的语句写法,供您参考,希望可以让您对SQL Server创建表方面有更深的认识. USE suntest ...

  8. SQL Server创建表和添加列

    撰写时间:2022 年 4 月 27日 SQLServer创建表和添加列 SQL Server创建表: 表用于在数据库中存储数据:表在数据库和模式中唯一命名.每个表包含一个或多个列.每列都有一个相关的 ...

  9. 使用SQL Server创建表

    使用SQL Server创建表 一.CREATE TABLE语句简介: 表用于在数据库中存储数据. 表在数据库和模式中唯一命名. 每个表包含一个或多个列. 每列都有一个相关的数据类型,用于定义它可以存 ...

最新文章

  1. oracle导出客户机使用us7a,导入 Oracle WORLD SAMPLE
  2. 高并发下如何保证接口的幂等性?
  3. 上海交大机试真题—最短路径(最小生成树解法)
  4. python函数返回元组平均数_关于python:使用函数中的单个项返回元组
  5. 漫谈分布式事务的那些解决方案
  6. 加快发展设施业 农业大健康-林裕豪:从玉农业践行基础支撑
  7. mstar v56几路hdmi_Android TV : Mstar平台 GPIO 调试
  8. spring mvc import resource路径问题【最简单的却也是最致命的】
  9. UML学习-活动图创建
  10. 956. 最高的广告牌
  11. php生成svg图片不显示,css svg不显示不出来怎么办
  12. 【概念的辨异】—— ISO C 与 POSIX C(C standard library 与 C POSIX library)
  13. python存储机制_python学习之内存驻留机制简述
  14. 如何打开.jar文件?
  15. YUV444、YUV422、YUV420占用字节数
  16. 谱曲软件-MuseScore
  17. Sentinel限流熔断
  18. myecplice和ecplice远程调试
  19. 论文笔记 EMNLP 2020|Edge-Enhanced Graph Convolution Networks for Event Detection with Syntactic Relation
  20. 马云和他的少年阿里 百度云下载

热门文章

  1. 设计模式(Python)-观察者模式
  2. atos命令符化号crash文件
  3. 移动设备应用程序中支持多个屏幕大小和 DPI 值
  4. JS面向对象,__proto__和prototype详解
  5. C++---容器适配器(stack、queue、priority_queue)
  6. Webpack打包出错:Error: Cannot find module ‘webpack/lib/node/NodeTemplatePlugin‘ Require stack:
  7. Error:Comments are not permitted in JSON
  8. 【博客项目】—案例初始化(二)
  9. HTML的基本知识(六)——表格的基本属性之实现个人简历
  10. 有哪些讽刺性极强的文案?