Оператор INSERT конфликтует с ограничением FOREIGN KEY, но очевидного конфликта нет - PullRequest
0 голосов
/ 21 июня 2019

Я не уверен, почему я получаю эту ошибку, потому что никакие данные не вставляются в столбец, упомянутый в ошибке. Это поле PK, установленное в IDENTITY, поэтому значение заполняется автоматически при добавлении каждой записи. Предполагается, что функция вставляет запись в таблицу аудита, вызываемую триггером в исходной таблице. Вот ошибка и мой код.

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 голосов
/ 22 июня 2019

z_TTeamPlayers.intTeamAuditID ссылается на первичный ключ вашей таблицы аудита. В своем коде вы вставляете это значение в z_TTeamPlayers ... INSERT INTO Z_TTeamPlayers(intTeamAuditID..., пока оно еще не существует (как первичный ключ) в вашей таблице аудита ... таким образом, оно терпит неудачу.

Вот демоверсия.

Я понимаю, что вы пытаетесь провести аудит, но я не уверен в вашей бизнес-логике в командах и игроках. Кажется, ваш дизайн немного отсталый. Вы всегда можете использовать управление версиями в SQL Server.

Как вы, вероятно, захотите дизайн, похожий на этот взамен

...