我在SQL Server 2005数据库的一个表中有一个名为“InsertTime”的字段,当记录第一次插入数据库时,默认为“getDate()”。我希望确保此列不会再次更新。
这个列可以被设置为只读吗?还是有更好的方法可以避免开发人员编写所有的SQL语句来实现此功能?
我在SQL Server 2005数据库的一个表中有一个名为“InsertTime”的字段,当记录第一次插入数据库时,默认为“getDate()”。我希望确保此列不会再次更新。
这个列可以被设置为只读吗?还是有更好的方法可以避免开发人员编写所有的SQL语句来实现此功能?
IF EXISTS (SELECT name FROM sys.objects
WHERE name = 'ReadOnlyInsertTime_tr' AND type = 'TR')
DROP TRIGGER dbo.ReadOnlyInsertTime_tr;
GO
CREATE TRIGGER ReadOnlyInsertTime_tr
ON dbo.MyTable
AFTER UPDATE
AS
IF (UPDATE(InsertTime))
BEGIN
ROLLBACK
-- Raise an informative error
-- RAISERROR (50009, 16, 10)
END;
GO
AFTER INSERT
触发器中编写 InsertTime
,那么你需要在该触发器的持续时间内禁用该触发器。 - satnhakALTER TRIGGER trgDocuments
ON dbo.Documents
FOR INSERT, UPDATE
AS
-- For new records set the created date and the updated date to Now
UPDATE Documents SET DateCreated = GetDate(), DateUpdated = GetDate() Where DocumentId in (SELECT DocumentId From inserted)
-- For updated records set the created date to the original created date and the updated date to Now
UPDATE Documents SET DateCreated = (SELECT DateCreated FROM deleted d WHERE DocumentId = d.DocumentId) Where DocumentId in (SELECT DocumentId From deleted)
UPDATE Documents SET DateUpdated = GetDate() Where DocumentId in (SELECT DocumentId From deleted)
一个代替触发器也可以完成这个工作。
CREATE TRIGGER [dbo].[MyTableUpdateTrigger]
ON [dbo].[MyTable]
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON
UPDATE MyTable
SET Column1 = Inserted.Column1
,Column2 = Inserted.Column2
-- Don't set this for the "InsertTime" field.
FROM Inserted
INNER JOIN MyTable
ON Inserted.TheKey = MyTable.TheKey
END
我最近实现了一个非常类似的解决方案,并且不得不克服许多障碍,所以我在这里发布解决方案,希望它能有所帮助。
我想做的是拥有一个由数据库而不是用户代理管理的RecordCreated和LastModified列。在这种情况下,RecordCreated将是插入行时的日期时间,而LastModified将是最后更新行的时间。我还想防止用户直接修改这些列。这是我所做的:
将这两个列作为可空SMALLDATETIME列添加到我的表中:
RecordCreated SMALLDATETIME,
LastModified SMALLDATETIME
CREATE TRIGGER dbo.WidgetProductionTrigger ON dbo.WidgetProduction AFTER INSERT, UPDATE AS BEGIN
触发器首先检查用户是否尝试插入/修改我的列的值。我遇到了一个问题,UPDATE()函数总是返回true,因此需要一些额外的逻辑:
DECLARE @RecordCreated SMALLDATETIME;
SELECT @RecordCreated = RecordCreated FROM INSERTED;
IF UPDATE(RecordCreated) AND NOT @RecordCreated IS NULL BEGIN
RAISERROR('RecordCreated is not user maintainable.', 16, 1);
ROLLBACK TRANSACTION;
RETURN;
END;
DECLARE @LastModified SMALLDATETIME;
SELECT @LastModified = LastModified FROM INSERTED;
IF UPDATE(LastModified) AND NOT @LastModified IS NULL BEGIN
RAISERROR('LastModified is not user maintainable.', 16, 1);
ROLLBACK TRANSACTION;
RETURN;
END;
IF EXISTS ( SELECT * FROM DELETED ) BEGIN
UPDATE dbo.WidgetProduction SET
LastModified = CAST(GETDATE() AS SMALLDATETIME)
WHERE ProductionRecordID IN (SELECT ProductionRecordID FROM INSERTED);
END ELSE BEGIN
UPDATE dbo.WidgetProduction SET
RecordCreated = CAST(GETDATE() AS SMALLDATETIME),
LastModified = CAST(GETDATE() AS SMALLDATETIME)
WHERE ProductionRecordID IN (SELECT ProductionRecordID FROM INSERTED);
END;
这个解决方案完全按预期工作。