日期创建和日期修改列的问题 - SQL Server

5
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 保持更改。换句话说,你能否写一个简单的触发器示例?我还不太了解......

2
在你的更新查询中,为什么不直接重置dateModified = GetDate()? - Aaron
1
我想要让它自动化... - user311509
7个回答

10
你可能需要考虑创建更新触发器来自动更新该值。可以参考类似的东西。
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

1
如果您的更新更改了主键(这真的很糟糕),使用INSERTED而不是DELETED不是更好吗?否则,此方法将无法正常工作。我是否遗漏了什么? - KM.

5
UPDATE
    Customer
SET
    ... = NewValue,
    dateModified = DEFAULT
WHERE
    ...

我建议使用这个方法而不是 dateModified = GETDATE(),这样GETDATE()只会被调用一次(如果你将来想要改成GETUTCDATE()的话)。

如果有多个更新路径,可以考虑使用触发器...


如果你真的必须这样做,搜索和替换在类似于GETDATE的东西上会相当有效。 - KM.

3
当我插入一条记录时,dateCreated和dateModified会被设置为默认的日期/时间。那么当我更新/修改记录时,dateCreated和dateModified会保留原样吗?我该怎么办?
只有在INSERT操作中才会使用列默认值,而不是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

我喜欢在过程的顶部使用本地变量集:
```html

我喜欢在过程的顶部使用本地变量集:

```
DECLARE @RunDate datetime
SET @RunDate=GETDATE()

我会在程序中使用这个时间戳,这样所有的更改(甚至是多个表格的更改)都会有精确到毫秒的相同日期。我还喜欢让dateModified列允许为空,并且没有默认值,当它被插入时,它是创建而不是修改,只有在实际修改时才会设置dateModified。

然后使用:

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

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

0

@astander说得对,如果你想要自动化,你应该使用一个更新触发器。我的更新触发器略有不同(我使用“inserted”虚拟表)。这里是一个适合你模式的触发器(根据需要进行重命名):

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

0

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

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

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

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

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


0

1) 一定要为主键创建索引。(我最近刚发现了这种错误。)

2) 您可以使用一个INSERT/UPDATE触发器代替单独的触发器,但会稍微降低效率。如果insert.DateCreated为空,则更新Vals.DateCreated,否则更新Vals.DateModified。


-2

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


4
TimeSpan? 在 SQL Server 中?!?!?我认为.NET框架中有TimeSpan,但是在SQL Server中肯定 没有,至少我所知道的任何版本都没有。 - marc_s
糟糕,我把单词写错了,应该是时间戳(timestamp),但我错误地写成了时间跨度(timespan)。 - Kronass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接