【发布时间】:2010-10-08 01:06:58
【问题描述】:
是否有一种特殊的方法可以在 MS Sql Server 表中声明 DateCreated 列,以便在创建时自动使用适当的时间戳填充它?
或者..当我进行查询时,我是否必须手动提供日期时间?
【问题讨论】:
标签: sql sql-server sql-server-2005 linq-to-sql datecreated
是否有一种特殊的方法可以在 MS Sql Server 表中声明 DateCreated 列,以便在创建时自动使用适当的时间戳填充它?
或者..当我进行查询时,我是否必须手动提供日期时间?
【问题讨论】:
标签: sql sql-server sql-server-2005 linq-to-sql datecreated
设置默认值是不够的,你应该添加一个触发器来防止更新:
CREATE TRIGGER UpdateRecord ON my_table
AFTER UPDATE AS UPDATE my_table
SET [CreatedDate] = ((SELECT TOP 1 [CreatedDate] FROM Deleted d where d.[id]=[id]))
【讨论】:
默认值有两个主要缺点。
这意味着您不能确定这些值没有在您的控制之外被修改。
如果您想要真正的数据完整性(以便确定行中的日期是创建日期),则需要使用触发器。
将列设置为当前日期的插入触发器和防止更改该列(或更准确地说,将其设置为其当前值)的更新触发器是实现 DateCreated 列的方法。
将列设置为当前日期的插入和更新触发器是实现 DateModified 列的方法。
(来自用户 Gabriel 的编辑 - 这是我按照描述实现此功能的尝试 - 我不是 100% 确定它是正确的,但我希望 OP 对其进行审核...):
CREATE TRIGGER [dbo].[tr_Affiliate_IU]
ON [dbo].[Affiliate]
AFTER INSERT, UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Get the current date.
DECLARE @getDate DATETIME = GETDATE()
-- Set the initial values of date_created and date_modified.
UPDATE
dbo.Affiliate
SET
date_created = @getDate
FROM
dbo.Affiliate A
INNER JOIN INSERTED I ON A.id = I.id
LEFT OUTER JOIN DELETED D ON I.id = D.id
WHERE
D.id IS NULL
-- Ensure the value of date_created does never changes.
-- Update the value of date_modified to the current date.
UPDATE
dbo.Affiliate
SET
date_created = D.date_created
,date_modified = @getDate
FROM
dbo.Affiliate A
INNER JOIN INSERTED I ON A.id = I.id
INNER JOIN DELETED D ON I.id = D.id
END
【讨论】:
我们在 CreatedDate 上有 DEFAULT 并且不使用触发器强制执行
有时我们想明确设置日期 - 例如如果我们从其他来源导入数据。
应用程序错误可能会干扰 CreateDate,或者对此心存不满的 DBA(我们没有非 DBA 直接连接到我们的 DB)
我想您可能会在 CreateDate 上设置列级权限。
折衷办法可能是让 INSERT TRIGGER 在 1:1 表中创建一行,以便该列位于主表之外。第二个表可以具有 SELECT 权限,其中主表具有 UPDATE 权限,因此不需要 UPDATE 触发器来防止对 CreateDate 的更改 - 这会在正常更新行时移除一些“权重”。
我想你可以在第二张表上设置一个 UPDATE/DELETE 触发器来防止更改(在正常情况下永远不会执行,所以“轻量级”)
虽然有点痛苦,但拥有额外的表......可能有一个表用于所有 CreateDates - TableName、PK、CreateDate。不过,大多数数据库架构师会讨厌这样...
【讨论】:
当然是。
这里有一个例子。
Create table #TableName
(
ID INT IDENTITY(1,1) PRIMARY KEY,
CreatedDate DATETIME NOT NULL DEFAULT GETDATE(),
SomeDate VARCHAR(100)
)
INSERT INTO #TableName (SomeDate)
SELECT 'Some data one' UNION ALL SELECT 'some data two'
SELECT * FROM #TableName
DROP TABLE #TableName
【讨论】:
您可以将列的默认值设置为“getdate()”
【讨论】: