我需要设置审核日志。我需要一种无需使用 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的插入/删除表?也许不吧。
答案 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