不使用插入或删除表的审核日志

时间:2018-09-30 22:36:52

标签: sql sql-server-2012

我需要设置审核日志。我需要一种无需使用 deleted insertted 表的方法。我正在使用SQL Server Management Studio 2012。

表A (第一条记录)。保险人和负责人是人的代码。

Id YearReview    Insurer   InsuranceResponsible    TicketNr  InsReviewId  ReviewDate Comment IdInsurance

124   2017        1496         2345                TK201705     1        2017-09-29    Test     234
119   2017        1567         4567                TK201608     2        2017-09-29    Axa      1024
45    2016        1567         4567                TK201608     1        2016-05-30    All      1024 

表A (几个月后 )**注:yearReview和IdInsurance-拥有两个相同的IdInsurance永远不会发生。因此,如果某人对某个特定的IdInsurance进行了保险审查,它将删除最后一条记录,但始终记录更改。要记录的是:@ Insurer,@ InsuranceResponsible,@ TicketNr,@ InsReviewId,@ comment。

Id YearReview    Insurer   InsuranceResponsible    TicketNr  InsReviewId  ReviewDate Comment IdInsurance

521   2018       2456         1459                TK201805     1        2018-09-29    Ti       1274
520   2017       1496         2345                TK201608     3        2018-09-29    Remove   1024     
124   2017       1496         2345                TK201705     1        2017-09-29    Test     234
119   2017       1567         4567                TK201608     2        2017-09-29    Axa      1024
45    2016       1567         4567                TK201608     1        2016-05-30    All      1024

表B-审核日志表-该表的头文件是由另一个人制作的(我认为在日志表中oldvalue和newvalue不好。但是现在我必须坚持使用这些表)。我这里既没有包含LastChangeUser也没有包含LastChangeDate,但是它们确实存在。

    Id    AlteredField  OldValue  NewValue  IdInsurance  CreationDate CreationUser Event

    34        n/a          n/a      n/a      1024         2016-05-30      1567   'New Review 2016'
    45      'InsReview'     1       2        1024         2017-09-29      1567   'Review 2017'
    46  
    (...)

    1000      n/a          n/a      n/a      1274         2018-09-29      2456   'NewReview 2018'  
    1001    'InsReview'     2       3        1024         2018-09-29     1486  'Review 2018'

我不确定是不可能的一种可能性...

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_UpdateTableLog] 
     @IdInsurance int
    ,@YearReview char(4)
    ,@Insurer int
    ,@InsuranceResponsible int
    ,@TicketNr nvarchar(50)
    ,@InsReviewId int
    ,@comment nvarchar(255)

AS
BEGIN
    SET NOCOUNT ON;


    DECLARE @OldInsurer int
    DECLARE @OldInsuranceResponsible int
    DECLARE @OldTicketNr nvarchar(50)
    DECLARE @OldInsReviewId int
    DECLARE @OldComment nvarchar(255)


    -- SELECT OLD VALUES IN TABLE A 
    SET @OldInsurer = (SELECT TOP 1 [Insurer] from tableA WHERE Id = @IdInsurance and YearReview=@YearReview )
    SET @OldInsuranceResponsible = (SELECT TOP 1 [InsuranceResponsible] from tableA WHERE Id = @IdInsurance and YearReview=@YearReview )
    SET @OldTicketNr = (SELECT TOP 1 [TicketNr] from tableA WHERE Id = @IdInsurance and YearReview=@YearReview )
    SET @OldInsReviewId = (SELECT TOP 1 [InsReviewId] from tableA WHERE Id = @IdInsurance and YearReview=@YearReview  ) 
    SET @OldComment = (SELECT TOP 1 [Comment] from tableA WHERE Id = @IdInsurance and YearReview=@YearReview )
    SET @OldIdInsurance = (SELECT TOP 1 [IdInsurance] from tableA WHERE Id = @IdInsurance and YearReview=@YearReview )


    -- INSURER: EVALUATE IF SOMETHING HAS CHANGED
        IF @OldInsurer is not NULL

        BEGIN
        IF @OldInsReviewId <> @InsReviewId
                BEGIN 
                          INSERT INTO TableB ('InsReview',@OldInsReviewId,@InsReviewId,@IdInsurance,getdate(),@Insurer, concat('Review ' + year(getdate()) )
                    END

    same reasoning for the remaining 4.
        END

        ELSE   -- FOR the case where there are no lines in table B to compare, meaning a new review..

            BEGIN 
                  INSERT INTO TableB ('N/A','n/a','n/a',@IdInsurance,getdate(),@Insurer, concat('New Review ' + year(getdate()) )
            END
       END

所以我的问题是:

1)您是否同意为获取上面所示的表B而设计的存储过程?

2)是否可以实现相同的表B,而无需声明变量并且不使用SQL Server 2012的插入/删除表?也许不吧。

1 个答案:

答案 0 :(得分:1)

我必须为此审计表模式建议使用deleted and inserted with UNPIVOT。问题要求在没有他们的情况下如何做到这一点...

问题中的存储过程将执行您要尝试执行的操作。读取旧值的部分可以改进。 /* Postgres AGE() Function */ CREATE OR REPLACE FUNCTION f_postgres_age(TIMESTAMP, TIMESTAMP) RETURNS VARCHAR(64) STABLE AS $$ -- Input: '1994-04-04 20:10:52', '2018-09-24 11:31:05' -- Output: 24 years 5 mons 19 days 15:20:13 SELECT CASE WHEN DATEDIFF(year, DATE_TRUNC('year', $1), DATE_TRUNC('year', $2)) > 0 THEN DATEDIFF(year, DATE_TRUNC('year', $1), DATE_TRUNC('year', $2)) || ' years ' ELSE '' END || CASE WHEN DATEDIFF(month, DATE_TRUNC('month', $1), DATE_TRUNC('month', $2)) - DATEDIFF(month, DATE_TRUNC('year', $1), DATE_TRUNC('year', $2)) > 0 THEN DATEDIFF(month, DATE_TRUNC('month', $1), DATE_TRUNC('month', $2)) - DATEDIFF(month, DATE_TRUNC('year', $1), DATE_TRUNC('year', $2)) || ' mons ' ELSE '' END || CASE WHEN DATEDIFF(day, DATE_TRUNC('day', $1)+1, DATE_TRUNC('day', $2)) - DATEDIFF(day, DATE_TRUNC('month', $1), DATE_TRUNC('month', $2)) > 0 THEN DATEDIFF(day, DATE_TRUNC('day', $1)+1, DATE_TRUNC('day', $2)) - DATEDIFF(day, DATE_TRUNC('month', $1), DATE_TRUNC('month', $2)) || ' days ' ELSE '' END || TO_CHAR((TIMESTAMP 'epoch' + ( DATEDIFF(second, $1, DATE_TRUNC('day', $1)+1 ) + DATEDIFF(second, DATE_TRUNC('day', $2), $2) ) * INTERVAL '1 Second '),'HH24:MI:SS') age $$ LANGUAGE SQL ; --SELECT f_postgres_age('1994-04-04 20:10:52', '2018-09-24 11:31:05'); FROM子句对于所有查询都是相同的,因为它们正在读取同一行,因此应该有一个查询。在旧版本中,该表会被重复读取,这会降低性能,并使数据库上的负载也减慢其他所有内容的运行速度。对于小表来说,这并不明显,但是由于只有几亿行,这种事情就大有不同。而且,由于我们已经确定Id和YearReview是唯一键,因此WHERE运算符是不必要的。

因此TOP会更好:

SELECT OLD VALUES IN TABLE A