我最终采用的解决方案是将inserted
anddeleted
表中的数据传输到索引表变量中,然后从那里使用它们。性能不如 CDC 好,但可以接受且呈线性,而且上市时间要短得多。我编写了一个代码生成器来生成触发器,我在下面包含了一个示例:
IF TRIGGER_NESTLEVEL(OBJECT_ID('TR_su_type_code_audit_log')) > 1 RETURN
DECLARE @user_key INT, @tp INT = 0
IF EXISTS(SELECT 1 FROM deleted) SET @tp += 1
IF EXISTS(SELECT 1 FROM inserted) SET @tp += 2
DECLARE @i TABLE (type_code_key int, audit_data VARCHAR(MAX), PRIMARY KEY (type_code_key))
DECLARE @d TABLE (type_code_key int, audit_data VARCHAR(MAX), PRIMARY KEY (type_code_key))
INSERT INTO @i SELECT type_code_key,
(SELECT type_code_key, type_code_group, id, description, is_system_reserved, site_key, code_int,
code_str, image_index, image_filename FOR XML RAW('audit'))
FROM inserted
INSERT INTO @d SELECT type_code_key,
(SELECT type_code_key, type_code_group, id, description, is_system_reserved, site_key, code_int,
code_str, image_index, image_filename FOR XML RAW('audit'))
FROM deleted
SET @user_key = dbo.f_get_current_user()
IF @tp = 2
BEGIN
INSERT INTO audit_trail (mod_type, mod_date, user_key, audit_rec_table, audit_rec_key, audit_rec_key_1,
audit_rec_key_2, is_delta, data_to)
SELECT 'I', GETDATE(), @user_key, 'su_type_code', t.type_code_key, NULL, NULL, 0, audit_data
FROM @i t
END ELSE IF @tp = 1
BEGIN
INSERT INTO audit_trail (mod_type, mod_date, user_key, audit_rec_table, audit_rec_key, audit_rec_key_1,
audit_rec_key_2, is_delta, data_from)
SELECT 'D', GETDATE(), @user_key, 'su_type_code', t.type_code_key, NULL, NULL, 0, audit_data
FROM @d t
END ELSE
BEGIN
INSERT INTO audit_trail (mod_type, mod_date, user_key, audit_rec_table, audit_rec_key, audit_rec_key_1,
audit_rec_key_2, is_delta, data_to, data_from)
SELECT 'U', GETDATE(), @user_key, 'su_type_code', t.type_code_key, NULL, NULL, 0, t.audit_data, d.audit_data
FROM @i t INNER JOIN @d d ON (t.type_code_key = d.type_code_key)
WHERE ISNULL(t.audit_data, '') <> ISNULL(d.audit_data, '')
END
SET NOCOUNT OFF;