INSERT语句与FOREIGN KEY约束冲突,但是没有明显的冲突

时间:2019-06-21 20:29:45

标签: sql sql-server insert foreign-keys

我不确定为什么会收到此错误,因为没有数据被插入到错误中提到的列中。这是一个设置为IDENTITY的PK字段,因此该值会随添加的每条记录自动填充。该功能应该在源表中的触发器调用的审计表中插入一条记录。这是错误和我的代码。

Msg 547, Level 16, State 0, Procedure tblTriggerAuditRecord_TTeamPlayers, Line 33 [Batch Start Line 344]

The INSERT statement conflicted with the FOREIGN KEY constraint "Z_TTeamPlayers_TTeams_FK". The conflict occurred in database "dbSQL1", table "dbo.Z_TTeams", column 'intTeamAuditID'.



--Problematic Code
DELETE FROM TTeamPlayers
DELETE FROM TTeams 
WHERE strTeam = 'Reds'

SELECT * FROM TTeams
SELECT * FROM Z_TTeams
=========================
-- both these tables are updated when a DELETE is run. I have the FK constraint set to CASCADE so that when it's deleted out of the child table Z_TTeamPlayers, the parent record is deleted.
CREATE TABLE Z_TTeamPlayers
(
     intTeamPlayerAuditID   INTEGER IDENTITY    NOT NULL
    ,intTeamAuditID         INTEGER             NOT NULL
    ,intPlayerAuditID       INTEGER             NOT NULL
    ,UpdatedBy              VARCHAR(50)         NOT NULL
    ,UpdatedOn              DATETIME            NOT NULL
    ,strAction              VARCHAR(10)         NOT NULL
    ,strModified_Reason VARCHAR(1000)
    --,CONSTRAINT PlayerTeam_UQ UNIQUE ( intTeamID, intPlayerID )
    ,CONSTRAINT Z_TTeamPlayers_PK PRIMARY KEY ( intTeamPlayerAuditID )
)

CREATE TABLE Z_TTeams
(
     intTeamAuditID     INTEGER IDENTITY    NOT NULL
    ,intTeamID          INTEGER             NOT NULL
    ,strTeam            VARCHAR(50)         NOT NULL
    ,strMascot          VARCHAR(50)         NOT NULL
    ,UpdatedBy          VARCHAR(50)         NOT NULL
    ,UpdatedOn          DATETIME            NOT NULL
    ,strAction          VARCHAR(10)         NOT NULL
    ,strModified_Reason VARCHAR(1000)   
    ,CONSTRAINT Z_TTeams_PK PRIMARY KEY ( intTeamAuditID )
)
==============================
ALTER TABLE Z_TTeamPlayers ADD CONSTRAINT Z_TTeamPlayers_TTeams_FK
FOREIGN KEY ( intTeamAuditID ) REFERENCES Z_TTeams ( intTeamAuditID ) ON DELETE CASCADE
==============================
-- --------------------------------------------------------------------------------
-- Create Trigger for Z_TTeamPlayers
-- --------------------------------------------------------------------------------
GO
CREATE TRIGGER tblTriggerAuditRecord_TTeamPlayers on TTeamPlayers
AFTER UPDATE, INSERT, DELETE
AS

    DECLARE @Now DATETIME
    DECLARE @Modified_Reason VARCHAR(1000)
    DECLARE @Action VARCHAR(10)
    SET @Action = ''

    -- Defining if it's an UPDATE, INSERT, or DELETE
    BEGIN
    IF (SELECT COUNT(*) FROM INSERTED) > 0
        IF (SELECT COUNT(*) FROM DELETED) > 0
            SET @Action = 'UPDATE'
        ELSE
            SET @Action = 'INSERT'
    ELSE
        SET @Action = 'DELETE'
    END

    SET @Now = GETDATE() -- Gets current date/time

        IF (@Action = 'INSERT')
            BEGIN -- Begin INSERT info
                INSERT INTO Z_TTeamPlayers(intTeamAuditID, intPlayerAuditID, UpdatedBy, UpdatedOn, strAction, strModified_Reason)
                SELECT I.intTeamID, I.intPlayerID, SUSER_NAME(), GETDATE(), @Action, I.strModified_Reason
                FROM INSERTED as I
                    INNER JOIN TTeamPlayers as T ON T.intTeamPlayerID = I.intTeamPlayerID
            END -- End Insert Info
        ELSE
            IF (@Action = 'DELETE')
                BEGIN -- Begin INSERT info
                    INSERT INTO Z_TTeamPlayers(intTeamAuditID, intPlayerAuditID, UpdatedBy, UpdatedOn, strAction, strModified_Reason)
                    SELECT D.intTeamID, D.intPlayerID, SUSER_SNAME(), GETDATE(), @Action, ''
                    FROM DELETED as D
                END -- End Delete Info
            ELSE -- @Action = 'UPDATE'
                BEGIN --begin UPDATE info get modified reason
                    IF EXISTS (SELECT TOP 1 I.strModified_Reason FROM INSERTED as I, TPlayers as T WHERE I.intPlayerID = T.intPlayerID
                                                                                                AND I.strModified_Reason <> '')
                        BEGIN -- beging insert of UPDATE info
                            INSERT INTO Z_TTeamPlayers(intTeamAuditID, intPlayerAuditID, UpdatedBy, UpdatedOn, strAction, strModified_Reason)   
                            SELECT I.intTeamID, I.intPlayerID, SUSER_SNAME(), GETDATE(), @Action, I.strModified_Reason
                            FROM TTeamPlayers as T
                                INNER JOIN INSERTED as I ON T.intPlayerID = I.intPlayerID
                            -- set modified reason column back to empty string
                            UPDATE TPlayers SET strModified_Reason = NULL
                            WHERE intPlayerID IN (SELECT TOP 1 intPlayerID FROM INSERTED)

                        END
                    ELSE
                        BEGIN -- begin if no modified reasson supplied
                            PRINT 'Error and rolled back, please enter modified reason'
                            ROLLBACK
                        END
                    END

1 个答案:

答案 0 :(得分:0)

z_TTeamPlayers.intTeamAuditID引用审核表的主键。在您的代码中,您正在将该值插入z_TTeamPlayers ... INSERT INTO Z_TTeamPlayers(intTeamAuditID...,而在审计表中尚不存在(作为主键)...因此失败。

Here is a demo.

我知道您正在尝试进行审核,但是我不确定您在团队和球员上的业务逻辑。您的设计似乎有些倒退。您始终可以在SQL Server中使用版本控制。

猜测您可能想要design similar to this instead