介绍 (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
GO
USE 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
GO
CREATE 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的插入触发器。 创建此插入触发器的目的是将每笔交易的进/出数量插入到审计表中。 在此触发器中,我们具有三个条件:
- 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. 首先,我们检查审核表中已经存在的项目。 如果不是,则将“入库数量”或“出库数量”插入审核表。
- 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. 如果存在数据,请检查同一日期的可用物料,然后更新输入和输出数量,并使用插入触发器中实现的逻辑来平衡所得数量。
- 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 data
create 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=@InventoryDate
IF(@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_InventoryMasters
SET 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;
END
ELSE
BEGIN
SELECT top 1 @Unit_Qty=ResultQty FROM Audit_InventoryMasters WHERE ItemNO=@ItemNO
AND
AuditDate < @InventoryDate --AND InventorySeq=@InventorySeq
order by AuditDate desc
END
IF(@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_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
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_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
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.
使用此更新触发器,清单主表结果上的每个更新将作为结果更新到审核表。
- 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. 首先,我们检查审核表中已经存在的项目。 如果存在,则更新输入和输出数量,并更新审核表中的所有剩余和结果。
- 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=@InventoryDate
IF(@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=@InventoryDate
and InventoryType='I'
SELECT @result_OUT_Qty=sum(Qty) FROM
InventoryMasters
WHERE
ItemNO=@ItemNO and
InventoryDate=@InventoryDate
and InventoryType='O'
IF(@InventoryType='I')
BEGIN
SELECT @result_IN_Qty_CHK=sum(InQty)
FROM Audit_InventoryMasters
WHERE
ItemNO=@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=@InventoryDate
and InventoryType='I'
IF(@ROWINCOUNT>1)
BEGIN
IF(@qty=0)
BEGIN
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty-(@result_IN_Qty_CHK-@result_IN_Qty)
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
ELSE
BEGIN
IF(@result_IN_Qty_CHK>=@result_IN_Qty)
BEGIN
SET @result_IN_Qty_CHK_1=@result_IN_Qty_CHK-@result_IN_Qty;
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty-@result_IN_Qty_CHK_1
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
ELSE
BEGIN
SET @result_IN_Qty_CHK_1=@result_IN_Qty-@result_IN_Qty_CHK;
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty+@result_IN_Qty_CHK_1
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
END
END
ELSE
BEGIN
IF(@Qty>=@New_QtyCheck)
BEGIN
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty+(@Qty-@New_QtyCheck)
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
ELSE
BEGIN
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty-(@New_QtyCheck-@Qty)
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
END
UPDATE 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_InventoryMasters
WHERE
ItemNO=@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=@InventoryDate
and InventoryType='O'
IF(@ROWINCOUNT>1)
BEGIN
IF(@qty=0)
BEGIN
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty+(@result_OUT_Qty_CHK-@result_OUT_Qty)
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
Else
BEGIN
IF(@result_OUT_Qty_CHK>=@result_OUT_Qty)
BEGIN
SET @result_OUT_Qty_CHK_1=@result_OUT_Qty_CHK-@result_OUT_Qty;
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty+@result_OUT_Qty_CHK_1
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
Else
BEGIN
SET @result_OUT_Qty_CHK_1=@result_OUT_Qty-@result_OUT_Qty_CHK;
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty+@result_OUT_Qty_CHK_1
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
END
END
ELSE
BEGIN
IF(@Qty>=@New_OUT_QtyCheck)
BEGIN
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty-(@Qty-@New_OUT_QtyCheck)
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
ELSE
BEGIN
UPDATE Audit_InventoryMasters SET
RemainingQty=RemainingQty+(@New_OUT_QtyCheck-@Qty)
WHERE
ItemNO=@ItemNO
and
AuditDate>@InventoryDate
END
END
UPDATE 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
where
InventoryDate='20161205'
and
ItemNO='I001'
and
InventoryType='I'
and
InventorySeq=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
where
InventoryDate='20161205'
and
ItemNO='I001'
and
InventoryType='O'
and
InventorySeq=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.
接下来,我们创建名为trInventoryDelete的审计更新触发器。
- 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和结果数量,并更新审核表中的所有剩余数量和结果数量。
- 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
GO
create 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=@InventoryDate
if(@DateCount>0)
BEGIN
if(@InventoryType='I')
Begin
select @ROWINCOUNT=count(*) from
InventoryMasters
where
ItemNO=@ItemNO and
InventoryDate=@InventoryDate
and InventoryType='I'
and InventorySeq=@InventorySeq
if(@ROWINCOUNT<=0)
BEGIN
select @Qty=InQty-(select isnull(sum(Qty),0) from
InventoryMasters
where
ItemNO=@ItemNO and
InventoryDate=@InventoryDate
and InventoryType='I')from
Audit_InventoryMasters
where
ItemNO=@ItemNO and
AuditDate=@InventoryDate
END
update Audit_InventoryMasters set InQty=InQty-@Qty
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
select @ROWINCOUNT=count(*) from
InventoryMasters
where
ItemNO=@ItemNO and
InventoryDate=@InventoryDate
and InventoryType='O'
and InventorySeq=@InventorySeq
if(@ROWINCOUNT<=0)
BEGIN
select @Qty=OutQty-(select isnull(sum(Qty),0) from
InventoryMasters
where
ItemNO=@ItemNO and
InventoryDate=@InventoryDate
and InventoryType='O')from
Audit_InventoryMasters
where
ItemNO=@ItemNO and
AuditDate=@InventoryDate
END
update Audit_InventoryMasters set OutQty=OutQty-@Qty
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
END
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
WHERE
InventoryDate='20161206'
and
ItemNO='I001'
and
InventoryType='I'
and
InventorySeq=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/