我们要创建一个通用日志文件,用于存储数据库中任何表的历史数据。为此,我们创建了表格
CREATE TABLE "COMMON_DATA_LOG" (
"UID" UNIQUEIDENTIFIER NOT NULL DEFAULT "NEWID"(),
"VID" UNIQUEIDENTIFIER NOT NULL,
"TABLE_NAME" VARCHAR(128) NOT NULL,
"COLUMN_NAME" VARCHAR(128) NOT NULL,
"COLUMN_VALUE" LONG BINARY NULL,
"KEY_VALUES" LONG BINARY NOT NULL,
"MODIFIED" TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
"MODIFIED_USER" VARCHAR(128) NOT NULL DEFAULT CURRENT USER,
PRIMARY KEY ( "UID" ASC )) IN "system";
UID
是通用行ID VID
是用于更改值的update语句的ID(如果已更新了几列)TABLE_NAME
包含更新后的表的名称COLUMN_NAME
包含已更改列的名称COLUMN_VALUE
包含已更改列的旧值KEY_VALUES
包含TABLE_NAME
的主键作为Blob,以标识已更改的行MODIFIED
简单时间戳MODIFIED_USER
更改数据的sql用户我们在表上使用触发器来填充此日志表,该表检查列是否已更改并将旧值存储在表COMMON_DATA_LOG
中。在表没有外键或简单的1-1关联的环境中,这很好用。
问题在于使用1-n和组合主键的表。读取关联表的记录值非常困难且缓慢。
假设下表
CREATE TABLE "Calendar_Recurrence" (
"KARECURRENCEUID" UNIQUEIDENTIFIER NOT NULL,
"KAFREQ" VARCHAR(50) NOT NULL DEFAULT 'DAILY',
"KAUNTIL" INTEGER NULL,
"KAINTERVAL" INTEGER NOT NULL DEFAULT 1,
"KABYDAY" VARCHAR(50) NULL,
"KABYMONTHDAY" INTEGER NULL,
"KABYMONTH" INTEGER NULL, PRIMARY KEY ( "KARECURRENCEUID" ASC )) IN "system";
CREATE TABLE "Calendar_Recurrence_Date" (
"KARECURRENCEUID" UNIQUEIDENTIFIER NOT NULL,
"KASEQUENCE" INTEGER NOT NULL,
"KASTARTTIME" "datetime" NOT NULL,
"KAENDTIME" "datetime" NOT NULL, PRIMARY KEY ( "KASEQUENCE" ASC, "KARECURRENCEUID" ASC )) IN "system";
关联人
ALTER TABLE "Calendar_Recurrence_Date" ADD CONSTRAINT "Calendar_Recurrence" NOT NULL FOREIGN KEY ( "KARECURRENCEUID" ASC ) REFERENCES "Calendar_Recurrence" ( "KARECURRENCEUID" );
如果我们遵循日志表,则表Calendar_Recurrence
将存储KEY_VALUES
仅KARECURRENCEUID
的旧值。表Calendar_Recurrence_Date
将存储KEY_VALUES
+ KARECURRENCEUID
的{{1}}的旧值。
要读取存储的值,我们必须选择从KASEQUENCE
开始的所有KEY_VALUES
,这将减慢查询速度并可能导致选择错误的数据。
在生产中,此场景有13个关联表。
是否有更好的通用方式存储历史记录?
我们的DBMS(Sql Anyhwere)不支持像Microsoft SQL Server中的“更改数据捕获”之类的功能。