2012-07-16 125 views
0

我创建了一个触发器,它在更改后创建了一个新行,并且新创建了一个新的行ID。当我使用触发器与一个表它的工作原理,但是当我用它在具有引用其它表的表,我得到一个错误:删除后SQL Server触发器与参考表冲突

DELETE statement conflicted with the REFERENCE constraint.

的表是这样的:

表1

ID  BEZEICHNUNG  MENGENEINHEIT  PREIS ..... 
1  Harry Potter  Book     20 
2  iPod    Music    150 

表2

DIENSTLEISTUNG_ID  RAUM_ID 
1      2 
2      1 

表3

ID  Raumname .... 
1  Elbe 
2  Main 

我的触发看起来是这样的:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER TRIGGER [dbo].[DIENSTLEISTUNG_Update] 
    ON [dbo].[DIENSTLEISTUNG] 
    AFTER UPDATE 
AS 
BEGIN 
SET NOCOUNT ON; 

    DECLARE @MAX_ID INT; 
    SELECT @MAX_ID=MAX(ID) FROM [DIENSTLEISTUNG]; 

    declare @tmp Table(ID numeric, BEZEICHNUNG nvarchar(64), MENGENEINHEIT nvarchar(64), 
    PREIS numeric(19,5), BESCHREIBUNG nvarchar(64), VORLAUFZEIT numeric(10), 
    AZ_MO nvarchar(22), AZ_DI nvarchar(22),AZ_MI nvarchar(22),AZ_DO nvarchar(22),AZ_FR nvarchar(22), 
    AZ_SA nvarchar(22),AZ_SO nvarchar(22),DIENSTLEISTUNGSART_ID numeric(38), 
    UPDATE_USER numeric(38), UPDATE_DATE datetime, RUESTZEIT numeric(38), 
    PERMISSIONS numeric (38), KONTRAKTPOSITION numeric(38),ARTIKELNUMMER nvarchar(64), 
    ANZAHL numeric(10), BUCHUNGSHINWEIS nvarchar(255), SONDERWUNSCH char(1), 
    FLAG bit) 

    insert into @tmp 
    select 
    ID, BEZEICHNUNG, MENGENEINHEIT, 
    PREIS, BESCHREIBUNG, VORLAUFZEIT, 
    AZ_MO, AZ_DI,AZ_MI,AZ_DO,AZ_FR, 
    AZ_SA,AZ_SO,DIENSTLEISTUNGSART_ID, 
    UPDATE_USER, UPDATE_DATE, RUESTZEIT, 
    PERMISSIONS, KONTRAKTPOSITION,ARTIKELNUMMER, 
    ANZAHL, BUCHUNGSHINWEIS, SONDERWUNSCH, 
    1 [flag] from deleted; 


    delete T from DIENSTLEISTUNG T JOIN @tmp I 
    ON T.ID=I.ID 

SET IDENTITY_INSERT [DIENSTLEISTUNG] ON 
INSERT INTO [DIENSTLEISTUNG] (ID, BEZEICHNUNG, MENGENEINHEIT, 
    PREIS, BESCHREIBUNG, VORLAUFZEIT, 
    AZ_MO, AZ_DI,AZ_MI,AZ_DO,AZ_FR, 
    AZ_SA,AZ_SO,DIENSTLEISTUNGSART_ID, 
    UPDATE_USER, UPDATE_DATE, RUESTZEIT, 
    PERMISSIONS, KONTRAKTPOSITION,ARTIKELNUMMER, 
    ANZAHL, BUCHUNGSHINWEIS, SONDERWUNSCH, 
    FLAG) 
SELECT @MAX_ID+ROW_NUMBER() OVER(ORDER BY ID) [ID],BEZEICHNUNG, MENGENEINHEIT, 
    PREIS, BESCHREIBUNG, VORLAUFZEIT, 
    AZ_MO, AZ_DI,AZ_MI,AZ_DO,AZ_FR, 
    AZ_SA,AZ_SO,DIENSTLEISTUNGSART_ID, 
    UPDATE_USER,GETDATE(),RUESTZEIT, 
    PERMISSIONS, KONTRAKTPOSITION,ARTIKELNUMMER, 
    ANZAHL, BUCHUNGSHINWEIS, SONDERWUNSCH, 
    0 
FROM INSERTED 
union all 
select * from @tmp 

SET IDENTITY_INSERT dbo.DIENSTLEISTUNG OFF 
SET NOCOUNT OFF; 
END; 
+0

足够简单:您试图删除仍在被行引用的内容。这是具有参照完整性(外键)的完整点 - 你不应该这样做!找出你想要删除的内容,还有哪些其他行仍然指向它。 – 2012-07-16 07:58:11

回答

3

这是发生的原因是因为虽然你重新插入使用相同的ID一排,在当您删除行时,SQL无法知道您将重新插入它以保持参照完整性。

看起来这个触发器的目的是不允许更新,并且在发生改变时插入一个新行,所以我认为INSTEAD OF触发器更适合您的需求。然后您可以忽略对现有行进行的任何更改,并插入新行,从而避免任何删除操作,从而避免参考完整性问题。

ALTER TRIGGER [dbo].[DIENSTLEISTUNG_Update] 
    ON [dbo].[DIENSTLEISTUNG] 
    INSTEAD OF UPDATE 
AS 
BEGIN 
    INSERT INTO [DIENSTLEISTUNG] (BEZEICHNUNG, MENGENEINHEIT, 
     PREIS, BESCHREIBUNG, VORLAUFZEIT, 
     AZ_MO, AZ_DI,AZ_MI,AZ_DO,AZ_FR, 
     AZ_SA,AZ_SO,DIENSTLEISTUNGSART_ID, 
     UPDATE_USER, UPDATE_DATE, RUESTZEIT, 
     PERMISSIONS, KONTRAKTPOSITION,ARTIKELNUMMER, 
     ANZAHL, BUCHUNGSHINWEIS, SONDERWUNSCH, 
     FLAG) 
    SELECT BEZEICHNUNG, MENGENEINHEIT, 
     PREIS, BESCHREIBUNG, VORLAUFZEIT, 
     AZ_MO, AZ_DI,AZ_MI,AZ_DO,AZ_FR, 
     AZ_SA,AZ_SO,DIENSTLEISTUNGSART_ID, 
     UPDATE_USER,GETDATE(),RUESTZEIT, 
     PERMISSIONS, KONTRAKTPOSITION,ARTIKELNUMMER, 
     ANZAHL, BUCHUNGSHINWEIS, SONDERWUNSCH, 
     0 
    FROM INSERTED 

    UPDATE DIENSTLEISTUNG 
    SET  Flag = 1 
    FROM DIENSTLEISTUNG 
      INNER JOIN INSERTED 
       ON INSERTED.ID = DIENSTLEISTUNG.ID 

END 
+0

谢谢,但我怎样才能将编辑后的行设置为更改后的值为1的标志 – 2012-07-16 08:21:24

+0

我已经添加了更新语句来执行此操作。 – GarethD 2012-07-16 08:34:28

+0

非常感谢你的工作! – 2012-07-16 08:39:43