首先指出我和楼主对题目理解不同的几点:
1. In the future, even though records can be updated or deleted-所以我认为这里只是指Update 和Delete 而不包括insert。
2. I do SELECT * FROM dbo.data1_PIT('2011-12-31', '2018-02-22 14:42:22')-这里的dbo.data1_PIT 是function的名字,不是指原始的table: data1;题目中并没有说history log要从原始table data1中选出. 我是这样理解的,用delete 做例子,既然delete已经发生,原始data1 table里就不会再存在那条信息,又如何能从原始table: data1里select那条信息呢? 别的公司我不知道, 我们公司是原始table delete records, 然后只在audit table 中保留历史记录,用于万一需要revert的时候用。
帮楼主把Trigger 和Function写好了, 也在我电脑上简单测试了一下,运行没问题。 刚毕业都不容易,特别是女生做developer可能会更难一些。祝楼主好运 。
---Create Trigger-I used delete as an an example;but this trigger can be modified to use for all update/delete/insert.
Create trigger Demo_Trigger
on data1
for delete
as
begin
set nocount on
insert into data_audit_data1
(date, id_security,changedate,ChangeUser,column6,column7)
select date, id_security,getdate(),SUser_SName(),column6,column7 ---I only used two columns as example, but you can reference all the columns
from deleted
end
go
---Test--Delete any row from data1 to confirm the history log will be inserted into the audit table: data_audit_data1
delete from data1
where date='1976-12-31' and id_security=57 and column6='2030' ---This is the first row in your sample table: data1; you can delete any other row as well.
---Create function: dbo.data1_PIT
Create function dbo.data1_PIT
(@OriginalDate datetime, @ChangeDate datetime)
returns table
as
return
select date,id_security,column6, column7 from data_audit_data1 where date=@OriginalDate and changedate=@ChangeDate
go
---Use function: dbo.data1_PIT to retrieve data that has been deleted above (See attached screenshot below for testing result)
select * from dbo.data1_PIT ('1976-12-31 00:00:00.000','2018-04-21 16:13:52.430')
然鹅我不会写所以你要改她的那个 function 里面的逻辑。
CREATE FUNCTION [dbo].[data1_PIT](@data_date smalldatetime, @as_of_date datetime)
RETURNS TABLE
AS
RETURN
IF EXISTS (SELECT * FROM data_audit.data1 AS DA WHERE DA.date = @data_date AND DA.ChangeDate >= @as_of_date)
WITH cte AS
(
SELECT DA.*, ROW_NUMBER() OVER(PARTITION BY DA.id_security ORDER BY DA.ChangeDate) AS rk
FROM data_audit.data1 AS DA WHERE DA.date=@data_date AND DA.ChangeDate >= @as_of_date)
)
SELECT date,
id_security,
column6,
column7,
FROM cte
where rk = 1;
ELSE
SELECT D.* FROM dbo.data1 AS D WHERE date = @data_date
END
大爷,我就这一招。 你行你up 给我们看看 怎么搭讪。和美女搭讪也不能光靠贬低自己水平……
您写的changedate<=@ChangeDate会把这个row自创建以来一直到@ChangeDate的所有update/delete的log都return出来的,根据要求,我们只想return出一条row。而且应该是在@ChangeDate之后的第一条row。原因是无论是delete还是update存进audit table都是被删除的row。mimi已经做出来了并且简明易懂,唯一个逻辑上需要修改的地方红色部分已经指出
打个比方现在是 2019年1月1日,我们要查询2018年4月21日那个时候的结果。 那么在function里面 @ChangeDate = '2018-04-21 0:0:0.000', 我们只需要在函数里面限定changedate<=@ChangeDate 就可以了。
因为任何在2018-04-21之后的修改删除都是新的纪录纪录在deleted表里面。跟你要查询的这个时间无关。
仅供参考。
多谢mimi的code。
---Create Trigger-I used delete as an an example;but this trigger can be modified to use for all update/delete/insert.
Create trigger Demo_Trigger
on data1
after delete,update
as
begin
set nocount on
insert into audit_data1
(date, id_security,changedate,ChangeUser,column6,column7)
select date, id_security,getdate(),ChangeUserName,column6,column7 ---I only used two columns as example, but you can reference all the columns
from deleted
end
go
---Test--Delete any row from data1 to confirm the history log will be inserted into the audit table: data_audit_data1
delete from data1
where date='1976-12-31' and id_security=57 and column6='2030' ---This is the first row in your sample table: data1; you can delete any other row as well.
---Create function: dbo.data1_PIT
Create function dbo.data1_PIT
(@OriginalDate datetime, @ChangeDate datetime)
returns table
as
return
select date,id_security,column6, column7 from audit_data1 where date=@OriginalDate and changedate<=@ChangeDate
go
---Use function: dbo.data1_PIT to retrieve data that has been deleted above (See attached screenshot below for testing result)
select * from dbo.data1_PIT ('1976-12-31 00:00:00.000','2018-04-21 16:13:52.430')
美女姐姐别生气,我说的有些绕,xiaoa表达的比我清楚。您的思路是对的,只是跟面试官的要求不太一致。面试官后来还加了一句hint:
I also wanted to give you few hints about my own solution:
I decided to use Table-Valued User-Defined Function
I created function: dbo.data1_PIT(@data_date smalldatetime, @as_of_date datetime).
The function returns data for one date, in structure identical to the structure of dbo.data1
According to my simple measurements, overhead of SELECT * statement over our live table is just 10%.
我再看看tutorial怎么写function吧。这个操作的话inline table-valued function可以实现吗?我要从两个table里select的话是不是要写multi statement的那种?
给你点个赞。你做的已经足够好了。我是按英文这部分来理解给的建议。我的理解可能是错的,不过我也只是好心给出我的看法而已。我们做project 的话都有详细的project doc, 所以不存在理解有分歧的情况。因为如果什么理解有歧义,在写code 之前就会找 stakeholder 问明白了。呵呵。我
不是很理解楼主的题目,所以不好意思帮不到楼主。之前楼主说不会写function的 syntax, 我的例子中至少syntax 是对的,楼主可以按你的理解改一下来用吧。
面试题是:Create SQL objects to return Point-in-time data that generate past results
To be more clear
- Create SQL object to show data in the same structure as dbo.data1 but as of certain date/time.
- Now time is 2018-02-22 14:42:22.
- I do SELECT * FROM dbo.data1 WHERE date = '2011-12-31'
- and get some records.
- In the future, even though records can be updated or deleted, if
- I do SELECT * FROM dbo.data1_PIT('2011-12-31', '2018-02-22 14:42:22')
- I will have to get identical output as I see now with the query under a.a (SELECT * FROM dbo.data1 WHERE date = '2011-12-31')
- Based on the code in triggers, I would like you to elaborate on:
- Our approach to data audits. Triggers and PIT functions are generated automatically with stored procedure, so maintenance is not a problem.
- Ideas for improvement. There is certainly room for improvement.
- Is SQL 2008/12/16 built in audit better solution? We audit just selected tables.
- Any suggestions for audit table compression and/or partitioning.