SQL Server触发器将数据插入或更新到单独的表中

时间:2015-02-25 17:43:47

标签: sql-server triggers sql-server-2012

我正在编写一个SQL Server 2012插入触发器,需要在一个单独的表中有条件地插入或更新现有行。

每个插入的行都需要单独计算,并且可能会在一次提交中插入多行。

触发器所在的表只能插入。有一个业务要求,对于给定的AlarmId,初始插入将用于设置警报的信息,并且将忽略该AlarmId的后续插入,除非该插入包含{{ 1}},此时复制的数据将更新为包含EndTime

因此,该表的相关部分将是:

EndTime

(极简化)触发器如下:

ID | AlarmId | StartTime | EndTime

我们这里没有T-SQL开发人员,因此非常感谢任何有关如何解决此问题的帮助。我相信光标是走到这里的正确方式,但我不确定,并且对任何想法持开放态度。

3 个答案:

答案 0 :(得分:2)

人们使用触发器犯的最大错误是假设插入和/或删除的集合只包含一行。插入很可能,并且几乎可以确定更新和删除,可能会有多行。

你当然也想避免游标。特别是在触发器中。表现太糟糕了。

这里有一个简单的基于集合的解决方案,这将是:

UPDATE dt
   SET column=value, etc, etc
  FROM destinationTable dt
       INNER JOIN inserted i ON dt.AlarmId = i.AlarmId 

INSERT INTO destinationTable (your list of columns here)
    SELECT (list of columns)
      FROM inserted i
     WHERE NOT EXISTS (SELECT 1 FROM destinationTable WHERE AlarmId = i.AlarmId)

INSERT仅插入数据尚不存在的位置... UPDATE仅更新已存在的行。

我希望这会有所帮助。

答案 1 :(得分:1)

我认为这应该作为插入触发器工作:

update d
set d.EndTime = i.EndTime
from 
  destinationTable d
  join inserted i on i.AlarmId = d.AlarmId
where
  i.EndTime is not NULL

insert into destinationTable (AlarmId,StartTime,EndTime)
select AlarmId, StartTime, EndTime 
from inserted i
where not exists (select 1 from destinationTable d
  where d.AlarmId = i.alarmId)

没有测试过这个,但希望它有效。如果您还对表格进行了更新,那么您必须单独处理。

答案 2 :(得分:0)

create table dbo.t5   (
    id int identity,
    AlarmId  int,
    StartTime datetime, 
    EndTime datetime
   )
   ;
   go

   create table 
    dbo.watched   (alarmid int,
   endtime datetime)
   ;
   go


create trigger dbo.t1 on dbo.watched after insert as
begin

set nocount on

Declare @AlarmId AS INT

Declare @endtime datetime

Select @AlarmId =AlarmId FROM inserted

Select @endtime = endtime from inserted

IF  exists (SELECT  AlarmId FROM dbo.t5 WHERE AlarmId = @AlarmId)

/* we already have an entry for this alarmid */

    BEGIN
       if @endtime is not null 
/* is this the terminal entry? */ 

       begin
        select 'hello'
        update  dbo.t5 set EndTime = @endtime where AlarmId = @Alarmid
       end
    END
ELSE
    /* first time seeing this alarmid - create it */

    BEGIN
        insert into dbo.t5 (AlarmID,StartTime)
                        values (@AlarmId, GETDATE())
    END
end
; go

insert into dbo.watched (alarmid) values (1234)

insert into dbo.watched (alarmid) values (1234)

select * from dbo.t5

insert into dbo.watched (alarmid,endtime) 
           values (123, GETDATE())

select * from dbo.t5 where AlarmId=123

dbo.t5将成为您的跟踪表。必须添加许多空白行,以便您可以剪切和粘贴示例。喜欢使用exist代替count(*),但count(*)也可以。 Exist可能更快。