有没有简单的方法在MS SQL中创建一个跟踪上次更新记录的列?
我想有两个字段。一个用于跟踪创建记录的时间。那个很简单。创建一个datetime字段并将其默认值设置为getdate()。然而,第二场接缝有点棘手。我希望它具有修改记录的最新日期(和时间)。
我的选择是:
还有其他选择吗?
答案 0 :(得分:5)
触发器几乎是你唯一的选择。什么是阻止任何人使用SSMS更新表,这些更新在这种情况下不会更新日期更新列
答案 1 :(得分:1)
选项4:
创建一个存储过程,自动为数据库中的所有表创建触发器。在SQL 2005中,可以选择在创建任何表时使用此触发器(使用DDL触发器)。
CREATE PROC UpdateTriggersCreate
AS
DECLARE
@TableSchema sysname,
@TableName sysname,
@PrimaryKeys nvarchar(4000),
@ObjectName nvarchar(4000)
@TriggerName nvarchar(4000),
@SQL nvarchar(4000);
SET @TableName = '';
SET @TableSchema = '';
WHILE 1 = 1 BEGIN
SELECT TOP 1
@TableSchema = TABLE_SCHEMA,
@TableName = TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
COLUMN_NAME = 'LastUpdatedDate'
AND (
TABLE_SCHEMA > @TableSchema
OR (
TABLE_SCHEMA = @TableSchema
AND TABLE_NAME > @TableName
)
)
ORDER BY TABLE_SCHEMA, TABLE_NAME;
IF @@RowCount = 0 BREAK;
IF NOT EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
WHERE
C.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND C.TABLE_SCHEMA = @TableSchema
AND C.TABLE_NAME = @TableName
) BEGIN
PRINT '-- Not processing table ''' + @TableSchema + '.' + @TableName + ''' because automatic last updated triggers cannot be used on tables with no primary key.';
CONTINUE;
END;
SET @PrimaryKeys = NULL;
SELECT @PrimaryKeys = Coalesce(@PrimaryKeys + ' AND T.', 'T.') + QuoteName(Y.COLUMN_NAME) + ' = I.' + QuoteName(Y.COLUMN_NAME)
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE Y
ON T.CONSTRAINT_CATALOG = Y.CONSTRAINT_CATALOG
AND T.CONSTRAINT_SCHEMA = Y.CONSTRAINT_SCHEMA
AND T.CONSTRAINT_NAME = Y.CONSTRAINT_NAME
WHERE
T.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND T.TABLE_SCHEMA = @TableSchema
AND T.TABLE_NAME = @TableName;
-- order is not important which is good because ORDER BY is unreliable in this case
SET @ObjectName = @TableSchema + '.' + @TableName;
SET @TriggerName = 'TR_' + Replace(@ObjectName, '.', '_') + '_U_TimeUpdated';
SET @SQL = 'IF Object_ID(''' + @TriggerName + ''', ''TR'') IS NOT NULL DROP TRIGGER ' + @TriggerName;
EXEC sp_executesql @SQL;
SET @SQL = 'CREATE TRIGGER ' + @TriggerName + ' ON ' + @ObjectName + ' FOR INSERT
AS
SET NOCOUNT ON
UPDATE T
SET T.LastUpdatedDate = GetDate()
FROM
' + @ObjectName + ' T
INNER JOIN Inserted I ON ' + @PrimaryKeys;
EXEC sp_executesql @SQL;
END;
一旦你有这样的存储过程,安排它每天运行一次或(在sql 2005及更高版本中)响应DDL创建表。
更新1
代码现在正确处理架构,并查找主键。它还报告并跳过没有主键的表。
我不确定我是否解决了所有语法错误 - 我从之前完成此操作的代码中修改了它并且实际上没有测试它。我相信你能搞清楚。
答案 2 :(得分:0)
存储过程是Access的一个选项,但您必须在VBA中拦截事件并调用存储过程,然后调用Me.Undo
。
我已经完成了,但是很多以前没有示例代码向您展示,抱歉。
否则触发是通常的方式,无论是在之前还是之后。