在触发器中,从insert获取值

时间:2011-12-16 13:30:00

标签: sql-server triggers

当我尝试创建此触发器时,我得到此异常:

The name "SITE_ID" is not permitted in this context. Valid expressions are constants, constant expressions, and (in some contexts) variables. Column names are not permitted.

CREATE TRIGGER tr_VISITACTIVITY_insert ON VISITACTIVITY
INSTEAD OF INSERT AS
BEGIN

    INSERT INTO [VISITACTIVITY]
               ([O_ID]
               ,[SITE_ID]
               ,[VISIT_DATE]
               ,[STAFF]
               ,[VISIT_TYPE_ID]
               ,[COMMENTS]
               ,[DELETED])
         VALUES
               (-1
               ,SITE_ID
               ,VISIT_DATE
               ,STAFF
               ,VISIT_TYPE_ID
               ,VISIT_COMMENTS
               ,0
               )
    GO

END
GO

程序员在应用程序中发出的插入是这样的:

    INSERT INTO [VISITACTIVITY]
           ([SITE_ID]
           ,[VISIT_DATE]
           ,[STAFF_COMMENT]
           ,[VISIT_TYPE_ID]
           ,[COMMENTS]
           )
     VALUES
           (15
           ,'2011-08-08'
           ,'Eric, John'
           ,6
           ,'invasives growing along the border of the preserve'
           )

因此,我需要程序员在insert中提供的值来在触发器中创建插入。

如何在触发器中引用这些值?

感谢。

1 个答案:

答案 0 :(得分:1)

您需要查看元表INSERTED,它基本上是一个包含所有插入数据的表,因此您引用(例如)SITE_IDinserted.SITE_ID }。

您还需要注意的是在触发器内进行单行插入(正如您似乎正在做的那样)。如果批处理中插入了多行,则INSERTED将包含多行。所以你需要做的是使用INSERT INTO table (...) SELECT ...,例如:

INSERT INTO [VISITACTIVITY]
       ([SITE_ID]
       ,[VISIT_DATE]
       ,[STAFF_COMMENT]
       ,[VISIT_TYPE_ID]
       ,[COMMENTS]
   )
   SELECT VISITACTIVITY, SITE_ID, VISIT_DATE, STAFF_COMMENT, VISIT_TYPE_ID, COMMENTS
       FROM inserted

顺便说一下,阅读你的问题,看起来你只是使用触发器来填充几列中的默认值。您是否考虑过只在表上使用DEFAULT约束?例如,如果您执行了以下操作:

ALTER TABLE VisitActivity ADD CONSTRAINT DF_VisitActivity_Deleted DEFAULT (0) FOR DELETED
ALTER TABLE VisitActivity ADD CONSTRAINT DF_VisitActivity_OID DEFAULT (-1) FOR O_ID

...那么这将使您的示例插入在没有触发器的情况下以相同的方式运行。这取决于您是否始终要覆盖Deleted或O_ID中的值。如果您总是想要覆盖,请使用触发器 - 或者更好的是,在列上粘贴CHECK以强制它为固定值(也会突出显示代码尝试更改它的位置,因为SQL Server将失败因参照完整性而插入)。如果您希望能够覆盖它,请使用DEFAULT约束。

(当然,你可能已经为了这个问题简化了问题,但我只是强调你如何在不诉诸触发的情况下做到这一点。)