SQL Server在提交之前触发INSTEAD OF INSERT以设置时间戳

时间:2013-11-11 21:07:25

标签: sql sql-server database tsql

在SQL Server 2008 R2中,我希望创建一个模仿Oracle BEFORE INSERT触发器行为的触发器,其中任何插入的触发器都会将UPDATE_TS和CREATE_TS更新为当前时间戳坚持不懈。

发布我现在看到的是错误:   只有在使用列列表且IDENTITY_INSERT为ON时,才能指定表'MY_TABLE'中标识列的显式值

我不确定将SET IDENTITY INSERT表打开然后再打开是否是个好主意 触发器中的SET IDENTITY INSERT表OFF。也许这是一个可能的解决方案。

请告知最佳做法。

示例表名为MY_TABLE:

CREATE TABLE [myschema].[MY_TABLE](
[MY_TABLE_ID] [bigint] IDENTITY(1,1) NOT NULL,
[FIELD_TO_UPDATE] [varchar](255) NOT NULL,
[CREATE_TS] [datetime] NULL,
[UPDATE_TS] [datetime] NULL),
PRIMARY KEY (MY_TABLE_ID))

触发:

CREATE TRIGGER my_table_create_ts_trigger 
ON [mydb].myschema.MY_TABLE
INSTEAD OF INSERT
AS
BEGIN
    INSERT INTO MY_TABLE([MY_TABLE_ID], [FIELD_TO_UPDATE], [CREATE_TS], [UPDATE_TS])
    SELECT i.MY_TABLE_ID, i.FIELD_TO_UPDATE, GETDATE(), GETDATE()
    FROM INSERTED as i
END

2 个答案:

答案 0 :(得分:6)

不确定为什么使用动态SQL,并不是真的需要它。此外,之后无需执行UPDATE,您可以这样做:

CREATE TRIGGER my_table_create_ts_trigger 
ON [mydb].myschema.MY_TABLE
INSTEAD OF INSERT
AS
BEGIN

    INSERT INTO MY_TABLE(<list of every non identity column here>)
    SELECT <list of every non identity column and the date here>, GETDATE()
    FROM INSERTED

END

此外,您应该在INSERTSELECT中明确列出列。

答案 1 :(得分:3)

我必须是一个贪婪的惩罚,但我有一个更好的建议。 放下触发器

将您的表格更改为:

CREATE TABLE [myschema].[MY_TABLE](
[MY_TABLE_ID] [bigint] IDENTITY(1,1) NOT NULL,
[FIELD_TO_UPDATE] [varchar](255) NOT NULL,

-- change this column to have a default:
[CREATE_TS] [datetime] NOT NULL DEFAULT CURRENT_TIMESTAMP,

-- and this column too, I guess:
[UPDATE_TS] [datetime] NOT NULL DEFAULT CURRENT_TIMESTAMP),

PRIMARY KEY (MY_TABLE_ID))

为什么要允许这些列为NULL?为什么要使用复杂的触发器来替换使用默认约束更简单的实现?

您不需要触发器,我不明白它带来了什么好处或者您想要复制BEFORE触发器的原因。 INSTEAD OF触发器类似,但不完全相同。