我有一个具有25列的3000条记录的表A。我想要一个称为表A历史的历史表,其中包含所有更改的更新和删除,以便我随时查看。我通常使用游标。现在考虑使用没有被要求的触发器。你有什么其他的建议?非常感谢!
答案 0 :(得分:0)
如果您使用的是tsql / SQL Server,并且不能使用触发器(这是获取所有更改的唯一肯定的方法),则可以使用在作业中安排的存储过程在每x倍的时间内运行一次,该存储过程在两个表中使用MERGE语句来获取新记录或更改。如果您需要毫无疑问地进行每一个更改,我都不建议这样做。
CREATE TABLE dbo.TableA (id INT, Column1 nvarchar(30))
CREATE TABLE dbo.TableA_History (id INT, Column1 nvarchar(30), TimeStamp DateTime)
(此代码不是生产性的,只是一般性的想法) 将以下代码放入存储过程中,并使用带有计划的Sql Server Job。
MERGE INTO dbo.TableA_History
USING dbo.TableA
ON TableA_History.id = TableA.id AND TableA_History.Column1 = TableA.Column1
WHEN NOT MATCHED BY TARGET THEN
INSERT (id,Column1,TimeStamp) VALUES (TableA.id,TableA.Column1,GETDATE())
因此,基本上,如果记录不存在或不匹配(意味着列已更改),请将记录插入历史记录表。
答案 1 :(得分:0)
即使您未使用SQL Server 2016并且系统版本表不可用,在某些情况下也可以创建不带触发器的历史记录。
在某些情况下,当您确定确定哪些例程正在修改表时,可以使用endpoint mysql:Client testDB1 {
host: "localhost",
port: 3306,
name: "customerdb",
username: "root",
password: "root",
poolOptions: { maximumPoolSize: 5, isXA:true },
dbOptions: { useSSL: false }
};
endpoint mysql:Client testDB2 {
host: "localhost",
port: 3306,
name: "salarydb",
username: "root",
password: "root",
poolOptions: { maximumPoolSize: 5, isXA:true },
dbOptions: { useSSL: false }
};
transaction with retries = 3, oncommit = onCommitFunction, onabort = onAbortFunction {
var retWithKey = testDB1->updateWithGeneratedKeys("INSERT INTO
CUSTOMER(NAME) VALUES ('Anne')", ());
string generatedKey;
match retWithKey {
(int, string[]) y => {
var (count, ids) = y;
generatedKey = ids[0];
io:println("Inserted row count: " + count);
io:println("Generated key: " + generatedKey);
}
error err => io:println("Insert to customer table failed: "
+ err.message);
}
ret = <int>generatedKey;
int key = -1;
match ret {
int retInt => key = retInt;
error err => io:println("Converting key to string failed: "
+ err.message);
}
io:println("Generated key for the inserted row: " + key);
ret = testDB2->update("INSERT INTO SALARY (ID, VALUE)
VALUES (?, ?)", key, 2500);
handleUpdate(ret, "Insert to SALARY table");
} onretry {
io:println("Retrying transaction");
}
clause创建历史记录。
例如
OUTPUT INTO
在例程中,当您使用INSERT INTO [dbo].[MainTable]
OUTPUT inserted.[]
,...
,'I'
,GETUTCDATE()
,@CurrentUserID
INTO [dbo].[HistoryTable]
SELECT *
FROM ... ;
时,我喜欢我们可以使用MERGE
:
仅可用于MERGE语句。指定类型的列 返回MERGE语句中OUTPUT子句中的nvarchar(10) 每行三个值之一:“ INSERT”,“ UPDATE”或“ DELETE”, 根据对该行执行的操作。
我们可以方便地添加$action
来修改表。使用触发器时,您需要使用会话上下文或会话变量来传递user
。在版本控制表中,您需要在主表中添加其他列,以便登录用户,因为它仅记录当前表的列(至少现在是这样)。
因此,基本上,这取决于您的数据和应用程序。如果表上有许多CRUD源,则触发是最安全的方法。如果您的表很大且使用率很高,那么使用user
是不好的,因为它会导致阻塞和损害性能。
在我们的数据库中,我们根据情况使用所有方法: