我需要向 SQL Server 2008 R2 中的数据库表添加两列:
- createTS - 插入行的日期和时间
- updateTS - 更新行的日期和时间
我有几个问题:
- 我应该为其中的每一个使用什么列数据类型?
createTS
只需在插入行时设置一次。当我尝试此列的datetime
类型并添加getdate()
的默认值或绑定(bind)时,列值已正确设置。这是实现本专栏目的的最佳方式吗?我考虑过timestamp
data type ,但在我看来,这几乎是一个用词不当!updateTS
需要设置为更新行时的日期和时间。在 SQL Server 中,没有 ON UPDATE CURRENT_TIMESTAMP (与 MySQL 中一样),所以看起来我必须求助于使用触发器。这是正确的吗?我该怎么做?
对于任何想回答这个问题的人来说,这是一个起点,这是创建表脚本:
CREATE TABLE [dbo].[names]
(
[name] [nvarchar](64) NOT NULL,
[createTS] [datetime] NOT NULL CONSTRAINT [DF_names_createTS] DEFAULT (getdate()),
[updateTS] [datetime] NOT NULL,
CONSTRAINT [PK_names] PRIMARY KEY CLUSTERED
(
[name] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
最佳答案
尝试
CREATE TABLE [dbo].[Names]
(
[Name] [nvarchar](64) NOT NULL,
[CreateTS] [smalldatetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
[UpdateTS] [smalldatetime] NOT NULL
)
PS 我认为小日期时间就足够了。您可能会做出不同的决定。
你能不能在“冲击时刻”这样做?
在 Sql Server 中,这很常见:
Update dbo.MyTable
Set
ColA = @SomeValue ,
UpdateDS = CURRENT_TIMESTAMP
Where...........
Sql Server 有一个“时间戳”数据类型。
但可能不是你想的那样。
这里有一个引用:
http://msdn.microsoft.com/en-us/library/ms182776(v=sql.90).aspx
这里有一点RowVersion ( synonym for timestamp ) 示例:
CREATE TABLE [dbo].[Names]
(
[Name] [nvarchar](64) NOT NULL,
RowVers rowversion ,
[CreateTS] [datetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
[UpdateTS] [datetime] NOT NULL
)
INSERT INTO dbo.Names (Name,UpdateTS)
select 'John' , CURRENT_TIMESTAMP
UNION ALL select 'Mary' , CURRENT_TIMESTAMP
UNION ALL select 'Paul' , CURRENT_TIMESTAMP
select * , ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]
Update dbo.Names Set Name = Name
select * , ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]
也许是一个完整的工作示例:
DROP TABLE [dbo].[Names]
GO
CREATE TABLE [dbo].[Names]
(
[Name] [nvarchar](64) NOT NULL,
RowVers rowversion ,
[CreateTS] [datetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
[UpdateTS] [datetime] NOT NULL
)
GO
CREATE TRIGGER dbo.trgKeepUpdateDateInSync_ByeByeBye ON dbo.Names
AFTER INSERT, UPDATE
AS
BEGIN
Update dbo.Names Set UpdateTS = CURRENT_TIMESTAMP from dbo.Names myAlias , inserted triggerInsertedTable where
triggerInsertedTable.Name = myAlias.Name
END
GO
INSERT INTO dbo.Names (Name,UpdateTS)
select 'John' , CURRENT_TIMESTAMP
UNION ALL select 'Mary' , CURRENT_TIMESTAMP
UNION ALL select 'Paul' , CURRENT_TIMESTAMP
select * , ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]
Update dbo.Names Set Name = Name , UpdateTS = '03/03/2003' /* notice that even though I set it to 2003, the trigger takes over */
select * , ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]
匹配“Name”值可能并不明智。
使用 SurrogateKey 尝试这个更主流的示例
DROP TABLE [dbo].[Names]
GO
CREATE TABLE [dbo].[Names]
(
SurrogateKey int not null Primary Key Identity (1001,1),
[Name] [nvarchar](64) NOT NULL,
RowVers rowversion ,
[CreateTS] [datetime] NOT NULL CONSTRAINT CreateTS_DF DEFAULT CURRENT_TIMESTAMP,
[UpdateTS] [datetime] NOT NULL
)
GO
CREATE TRIGGER dbo.trgKeepUpdateDateInSync_ByeByeBye ON dbo.Names
AFTER UPDATE
AS
BEGIN
UPDATE dbo.Names
SET UpdateTS = CURRENT_TIMESTAMP
From dbo.Names myAlias
WHERE exists ( select null from inserted triggerInsertedTable where myAlias.SurrogateKey = triggerInsertedTable.SurrogateKey)
END
GO
INSERT INTO dbo.Names (Name,UpdateTS)
select 'John' , CURRENT_TIMESTAMP
UNION ALL select 'Mary' , CURRENT_TIMESTAMP
UNION ALL select 'Paul' , CURRENT_TIMESTAMP
select * , ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]
Update dbo.Names Set Name = Name , UpdateTS = '03/03/2003' /* notice that even though I set it to 2003, the trigger takes over */
select * , ConvertedRowVers = CONVERT(bigint,RowVers) from [dbo].[Names]
关于sql-server - SQL Server 2008 行插入和更新时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17116334/