SQL 基于无datetime列基础表创建带最后修改时间的视图咨询
结论
仅使用常规查询视图无法直接实现该需求。核心原因是视图本身是仅做动态计算的虚拟表,没有持久化存储状态的能力,而你的两张原始表本身没有内置时间字段记录行的插入、更新时间,没有数据源支撑你判断关联记录是否发生变更、以及变更的具体时间,自然也没法实现「无变更时时间保持不变」的要求。
可行实现方案
下面给出两种不改动业务逻辑的实现方式,以SQL Server语法为例(你用到的getdate()是SQL Server内置函数):
方案1:给原表增加行时间字段(推荐)
这种方式性能最好,维护成本低。
步骤1:给两张原表增加时间字段与更新触发器
-- 给表A新增创建时间、更新时间字段,默认值为当前时间 ALTER TABLE 表A ADD created_time DATETIME DEFAULT GETDATE(); ALTER TABLE 表A ADD updated_time DATETIME DEFAULT GETDATE(); -- 创建表A的更新触发器,行数据变更时自动更新updated_time CREATE TRIGGER trg_表A_update ON 表A AFTER UPDATE AS BEGIN UPDATE 表A SET updated_time = GETDATE() FROM 表A INNER JOIN inserted ON 表A.Sno = inserted.Sno END -- 表B执行相同操作 ALTER TABLE 表B ADD created_time DATETIME DEFAULT GETDATE(); ALTER TABLE 表B ADD updated_time DATETIME DEFAULT GETDATE(); CREATE TRIGGER trg_表B_update ON 表B AFTER UPDATE AS BEGIN UPDATE 表B SET updated_time = GETDATE() FROM 表B INNER JOIN inserted ON 表B.Sno = inserted.Sno END
步骤2:创建关联视图
CREATE VIEW vw_关联结果 AS SELECT ISNULL(a.Sno, b.Sno) AS Sno, a.Name, b.City, -- 取关联两张行的最新更新时间作为整条记录的更新时间 CASE WHEN ISNULL(a.updated_time, '1900-01-01') > ISNULL(b.updated_time, '1900-01-01') THEN a.updated_time ELSE b.updated_time END AS lastupdatedtime FROM 表A a -- 若仅保留两张表都存在的Sno,可把FULL OUTER JOIN改为INNER JOIN FULL OUTER JOIN 表B b ON a.Sno = b.Sno
该方案完全符合你给出的示例逻辑:
- Sno为1的两条行都未更新,取初始的10:00 AM
- Sno为2的表B行有更新,取最新的11:00 AM
- Sno为3的两行都是新插入,取插入时间11:00 AM
方案2:新增独立变更日志表(不侵入原表结构)
如果不允许修改原表结构,可以新增独立的变更日志表记录所有行的变更时间:
-- 1. 建变更日志表 CREATE TABLE 变更日志 ( Sno INT, 操作时间 DATETIME DEFAULT GETDATE() ) -- 2. 给表A建插入、更新触发器,变更时写日志 CREATE TRIGGER trg_表A_change ON 表A AFTER INSERT, UPDATE AS BEGIN INSERT INTO 变更日志(Sno) SELECT Sno FROM inserted END -- 3. 给表B建相同触发器 CREATE TRIGGER trg_表B_change ON 表B AFTER INSERT, UPDATE AS BEGIN INSERT INTO 变更日志(Sno) SELECT Sno FROM inserted END -- 4. 创建关联视图 CREATE VIEW vw_关联结果 AS SELECT ISNULL(a.Sno, b.Sno) AS Sno, a.Name, b.City, l.最新操作时间 AS lastupdatedtime FROM 表A a FULL OUTER JOIN 表B b ON a.Sno = b.Sno LEFT JOIN ( SELECT Sno, MAX(操作时间) AS 最新操作时间 FROM 变更日志 GROUP BY Sno ) l ON ISNULL(a.Sno, b.Sno) = l.Sno
内容的提问来源于stack exchange,提问作者sami phani
相关产品推荐
相关产品推荐

