由于外键约束问题而插入A错误

时间:2012-10-25 14:37:31

标签: sql sql-server database sql-server-2008

有人可以帮我解释一下并解决它吗?

http://sqlfiddle.com/#!6/2adc7/9

INSERT语句与FOREIGN KEY约束“FK_tblMobileForms_tblForms”冲突。冲突发生在数据库“db_6_2adc7”,表“dbo.tblForms”,列'fm_id':插入到tblMobileForms(fm_name)值('lol')

我的架构有来自tblMobileForms的ID是tblForms.fm_id的外键

3 个答案:

答案 0 :(得分:3)

要执行您要执行的操作,您无法将tblMobileForms上的FK设置为​​标识。请参阅下面的小提琴以获取更多信息。

http://sqlfiddle.com/#!6/be6f7/2

或者你可以做的是让tblMobileForms拥有它自己独立的代理键,并且与tblForms表有不同的FK列。

答案 1 :(得分:1)

tblMobileForms表上的PK与同一个表上的FK同名。看到PK是IDENTITY列,您最终可能会得到不匹配的值。

在我的小提琴中,tblForms表包含60岁以上的ID。在子表中运行INSERT将添加id为1的记录,该记录在父表中不存在。

我在tblMobileForms表中创建一个新行,并将其引用到父表。

答案 2 :(得分:1)

您可以使用INSTEAD OF触发器在插入时为每个移动表单应用随机ID:

CREATE TRIGGER dbo.tblMobileForms_Insert
    ON dbo.tblMobileForms
    INSTEAD OF INSERT

AS
BEGIN
    DECLARE @Inserted TABLE (fm_ID INT, fm_html_file VARBINARY(MAX), fm_name NVARCHAR(50));
    INSERT @Inserted (fm_ID, fm_html_File, fm_Name)
    SELECT  fm_ID, fm_html_File, fm_Name
    FROM    inserted;

    IF EXISTS (SELECT 1 FROM @Inserted WHERE fm_ID IS NULL)
        BEGIN
            WITH NewRows AS
            (   SELECT  fm_ID, fm_html_File, fm_Name, RowNumber = ROW_NUMBER() OVER (ORDER BY fm_name)
                FROM    @Inserted
                WHERE   fm_ID IS NULL
            ), AvailableIDs AS
            (   SELECT  fm_ID, RowNumber = ROW_NUMBER() OVER (ORDER BY fm_ID)
                FROM    tblForms f
                WHERE   NOT EXISTS
                        (   SELECT  1
                            FROM    tblMobileForms m
                            WHERE   f.Fm_ID = m.fm_ID
                        ) 
                AND     NOT EXISTS
                        (   SELECT  1
                            FROM    inserted i
                            WHERE   f.fm_ID = i.fm_ID
                        ) 
            )
            UPDATE  NewRows
            SET     fm_ID = a.fm_ID
            FROM    NewRows n
                    INNER JOIN AvailableIDs a
                        ON a.RowNumber = n.RowNumber

            IF EXISTS (SELECT 1 FROM @Inserted WHERE fm_ID IS NULL)
                BEGIN 
                    RAISERROR ('Not enough free Form IDs to allocate an ID to the inserted rows', 16, 1);
                    RETURN;
                END
        END

        INSERT dbo.tblMobileForms (fm_ID, fm_html_File, fm_Name)
        SELECT  fm_ID, fm_html_file, fm_name
        FROM    @Inserted

END

当插入每一行时,触发器将检查tblForms中的下一个可用ID,并将其顺序应用于未指定fm_id的插入行。如果tblForms中没有空闲ID,则触发器将抛出错误,从而保持1对1的关系(因为tblMobileForms.fm_id也是PK,所以无论如何都会抛出错误。)

N.b。这要求tblForms.fm_ID只是一个int列,而不是identity。