【问题标题】:SQL Server trigger conflict with reference table after delete删除后 SQL Server 触发器与引用表冲突
【发布时间】:2012-07-16 16:34:05
【问题描述】:

我创建了一个触发器,该触发器在更改后使用新的ID 创建一个新行。当我将触发器与一个表一起使用时,它可以工作,但是当我在引用另一个表的表上使用它时,我收到一个错误:

DELETE 语句与 REFERENCE 约束冲突。

表格如下所示:

表 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;

【问题讨论】:

  • 很简单:您正在尝试删除仍被行引用的内容。这就是具有参照完整性(外键)的全部意义——你不应该这样做!找出您要删除的内容,以及其他哪些行仍然引用它。

标签: sql sql-server triggers


【解决方案1】:

发生这种情况的原因是,尽管您正在重新插入具有相同 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

【讨论】:

  • 谢谢,但是如何在更改后将已编辑的行设置为值为 1 的标志
猜你喜欢
  • 2020-09-30
  • 1970-01-01
  • 2017-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多