SQL Server:如何修改触发器以避免插入时崩溃?

时间:2020-12-27 04:18:55

I am using SQL Server 2012 on Windows 7.

我在Windows 7上使用SQL Server 2012。

I am a beginner in SQL; I currently have this trigger on a table DeviceStatus:

我是SQL的初学者;我目前在表DeviceStatus上有这个触发器:

ALTER TRIGGER [dbo].[trigger_insertInStatus] 
ON [dbo].[DeviceStatus] 
AFTER INSERT 
AS 
BEGIN
   -- Insert statements for trigger here:
   INSERT INTO GeneralStatus (DeviceIP, ServiceStatus)
   VALUES
   ( (SELECT DeviceIP FROM INSERTED), (SELECT ServiceStatus FROM INSERTED) );

END

where DeviceIP is a unique key.

其中DeviceIP是唯一键。

Problem is that, obviously, it crashes when trying to insert a record/row with a DeviceIP value that - accidentally - already exists in the second table named GeneralStatus...

问题是,显然,它在尝试插入具有DeviceIP值的记录/行时崩溃 - 意外 - 已存在于名为GeneralStatus的第二个表中...

How should I modify/adapt the above SQL query in order to keep the existing functionality (INSERT INTO...), but adding also the possibility to have the ServiceStatus column updated in such a case when the DeviceIP value already exists in the GeneralStatus table?
What's the best way to write this (performant, yet safe)?

我应该如何修改/调整上述SQL查询以保留现有功能(INSERT INTO ...),但是当GeneralIPatus表中已存在DeviceIP值时,还可以添加更新ServiceStatus列的可能性?写这个的最好方法是什么(高效,安全)?

2 个解决方案

#1


2  

Since Inserted has multiple rows, each of which can be an insert or update to GeneralStatus, you can join with inserted and check based on the row exists or not like this.

由于Inserted有多行,每一行都可以插入或更新到GeneralStatus,你可以加入插入和检查基于存在或不存在的行。

ALTER TRIGGER [dbo].[trigger_insertInStatus] 
   ON  [dbo].[DeviceStatus] 
   AFTER INSERT 
AS 
BEGIN

   --Update Records where DeviceIP does exist in GeneralStatus
   UPDATE GS 
   SET GS.ServiceStatus = I.ServiceStatus
   FROM GeneralStatus GS INNER JOIN Inserted I ON GS.DeviceIP = I.DeviceIP


   -- Insert statements for trigger here:
   -- Insert records where DeviceIP does not exist in GeneralStatus 
   INSERT INTO GeneralStatus
   ( DeviceIP,ServiceStatus )
   SELECT DeviceIP , ServiceStatus FROM INSERTED I
   LEFT JOIN GeneralStatus GS ON GS.DeviceIP = I.DeviceIP 
   WHERE GS.DeviceIP IS NULL;

END

#2


2  

INSERT INTO GeneralStatus
   ( DeviceIP, ServiceStatus )
 SELECT DeviceIP ,ServiceStatus FROM INSERTED I
where not exists(select 1 from generalstatus g where g.deviceip=i.deviceip)

#1


2  

Since Inserted has multiple rows, each of which can be an insert or update to GeneralStatus, you can join with inserted and check based on the row exists or not like this.

由于Inserted有多行,每一行都可以插入或更新到GeneralStatus,你可以加入插入和检查基于存在或不存在的行。

ALTER TRIGGER [dbo].[trigger_insertInStatus] 
   ON  [dbo].[DeviceStatus] 
   AFTER INSERT 
AS 
BEGIN

   --Update Records where DeviceIP does exist in GeneralStatus
   UPDATE GS 
   SET GS.ServiceStatus = I.ServiceStatus
   FROM GeneralStatus GS INNER JOIN Inserted I ON GS.DeviceIP = I.DeviceIP


   -- Insert statements for trigger here:
   -- Insert records where DeviceIP does not exist in GeneralStatus 
   INSERT INTO GeneralStatus
   ( DeviceIP,ServiceStatus )
   SELECT DeviceIP , ServiceStatus FROM INSERTED I
   LEFT JOIN GeneralStatus GS ON GS.DeviceIP = I.DeviceIP 
   WHERE GS.DeviceIP IS NULL;

END

#2


2  

INSERT INTO GeneralStatus
   ( DeviceIP, ServiceStatus )
 SELECT DeviceIP ,ServiceStatus FROM INSERTED I
where not exists(select 1 from generalstatus g where g.deviceip=i.deviceip)