关于 DateCreated 和 DateModified 列的问题 - SQL Server

Posted

技术标签:

【中文标题】关于 DateCreated 和 DateModified 列的问题 - SQL Server【英文标题】:Question About DateCreated and DateModified Columns - SQL Server 【发布时间】:2010-04-09 19:39:44 【问题描述】:
CREATE TABLE Customer
(
        customerID         int identity (500,20) CONSTRAINT 
        .
        .
        dateCreated    datetime DEFAULT GetDate() NOT NULL,
        dateModified   datetime DEFAULT GetDate() NOT NULL
);

当我插入一条记录时,dateCreated 和 dateModified 被设置为默认日期/时间。当我更新/修改记录时,dateModified 和 dateCreated 保持原样?我该怎么办?

显然,我需要 dateCreated 值保持第一次插入时的状态,并且当记录字段中发生更改/修改时,dateModified 会不断变化。

换句话说,你能写一个示例快速触发器吗?我还不太了解...

【问题讨论】:

在您的更新查询中,为什么不直接重置 dateModified = GetDate()? 我想让它自动... 【参考方案1】:

您可能希望创建一个更新触发器来为您更新此值

看看类似的东西

CREATE TABLE Vals(
        ID INT,
        Val VARCHAR(10),
        DateCreated DATETIME DEFAULT GetDate(),
        DateUpdated DATETIME DEFAULT GetDate()
)
GO

CREATE TRIGGER Upd ON Vals
AFTER UPDATE
AS 
UPDATE Vals
SET     DateUpdated = GetDate()
FROM    Vals INNER JOIN
        inserted ON Vals.ID = inserted.ID
Go

INSERT INTO Vals (ID, Val) SELECT 1, 'A'
SELECT *
FROM    Vals
GO

UPDATE Vals SET Val = 'B'
SELECT *
FROM    Vals
GO

DROP TABLE Vals
GO

【讨论】:

使用 INSERTED 而不是 DELETED 不是更好吗,如果您的更新更改了 PK(这真的很糟糕),这将不起作用,还是我遗漏了什么?【参考方案2】:
UPDATE
    Customer
SET
    ... = NewValue,
    dateModified = DEFAULT
WHERE
    ...

我会使用这个而不是dateModified = GETDATE(),所以 GETDATE() 只使用一次(假设你想在将来更改为 GETUTCDATE())

如果您有多个更新路径,则为触发器...?

【讨论】:

如果你真的需要,搜索和替换在GETDATE这样的东西上会很好用【参考方案3】:

当我插入一条记录时,dateCreated 并且 dateModified 被设置为默认值 约会时间。当我更新/修改 记录、日期修改和日期创建 保持原样?我该怎么办?

仅当INSERTing 时使用列默认值,而不是UPDATE。如果您不提供列或在 INSERT 中发出 DEFAULT 关键字,则 INSERT 命令将使用默认值。

INSERT INTO Customer (col1, col2) 
VALUES (..,..)  ---get default for dateCreated & dateModified   

INSERT INTO Customer (col1, col2,dateCreated) 
VALUES (..,..,DEFAULT)  ---get default for dateCreated & dateModified   

INSERT INTO Customer (col1, col2,dateCreated,dateModified) 
VALUES (..,..,DEFAULT,DEFAULT)  ---get default for dateCreated & dateModified   

INSERT INTO Customer (col1, col2,dateCreated,dateModified) 
VALUES (..,..,'1/1/2010',DEFAULT)  ---only get default for dateModified   

INSERT INTO Customer (col1, col2,dateCreated,) 
VALUES (..,..,'1/1/2010')  ---only get default for dateModified   

INSERT INTO Customer (col1, col2,dateCreated,dateModified)
VALUES (..,..,'1/1/2010','1/2/2010')  ---no defaults for dateCreated & dateModifie

我喜欢用一个局部变量来设置那个程序的顶部:

DECLARE @RunDate datetime
SET @RunDate=GETDATE()

然后我在过程中使用它,因此所有更改(即使在多个表上)都具有完全相同的毫秒日期。我也更喜欢 dateModified 列允许空值并且没有默认值,当它被插入时,它已创建未修改,我将在实际修改时设置 dateModified。

然后使用:

UPDATE Customer
    SET importantColumn=
       ,dateModified = @RunDate
    WHERE ...

UPDATE CustomerPrice
    SET importantColumn=
       ,dateModified = @RunDate
    WHERE ...

【讨论】:

【参考方案4】:

@astander 是对的,如果你想自动更新,你应该只使用更新触发器。我的更新触发器略有不同(我使用“插入”虚拟表)。这是一个应该适合您的架构(重命名,但您认为合适):

CREATE TRIGGER [CustomerDateModifiedTrigger] ON [dbo].[Customer] 
FOR UPDATE
AS
UPDATE Customer
SET dateModified = GETDATE()
FROM Customer c
INNER JOIN inserted i ON c.customerID = i.customerID

【讨论】:

【参考方案5】:

@Kronass,你根本不知道你在说什么!

timestamp 是 rowversion 数据类型的同义词,受数据类型同义词的行为影响。在 DDL 语句中,尽可能使用 rowversion 而不是 timestamp。有关详细信息,请参阅数据类型同义词 (Transact-SQL)。

Transact-SQL 时间戳数据类型不同于 ISO 标准中定义的时间戳数据类型。

不推荐使用时间戳语法。此功能将在 Microsoft SQL Server 的未来版本中删除。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。

rowversion (Transact-SQL) 是一种数据类型,可在数据库中公开自动生成的唯一二进制数。 rowversion 通常用作对表行进行版本标记的机制。存储大小为 8 个字节。 rowversion 数据类型只是一个递增的数字,不保留日期或时间。要记录日期或时间,请使用 datetime2 数据类型。

【讨论】:

【参考方案6】:

1) 一定要为主键创建索引。 (我最近才发现这种类型的错误。)

2) 您可以使用一个 INSERT/UPDATE 触发器而不是单独的触发器,但代价是效率损失很小。如果 insert.DateCreated 为 null,则更新 Vals.DateCreated,否则更新 Vals.DateModified。

【讨论】:

【参考方案7】:

SQL Server 中有一个数据类型叫做时间戳。每次修改行时都会跟踪行版本。 或者,如果您愿意,可以使用触发器并更改 ModifiedDate 列。

【讨论】:

时间跨度?在 SQL Server 中???真的?!?!??我认为 .NET 框架中有 TimeSpan - 但在 SQL Server 中肯定没有 - 至少我不知道 SQL Server 版本... 废话,我输入了错误的单词而不是时间戳,我错误地输入了时间跨度。

以上是关于关于 DateCreated 和 DateModified 列的问题 - SQL Server的主要内容,如果未能解决你的问题,请参考以下文章

覆盖 dateCreated 以在 Grails 中进行测试

XSLT选择当前级别不同属性的节点

进一步过滤 SQL 结果

将对象数据插入数组PHP [重复]

使用 GROUP BY 时如何选择分区内的最佳行

我每行都得到相同的结果