3

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

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 的外键

4

3 回答 3

3

要执行您尝试执行的操作,您不能将 tblMobileForms 上的 FK 设置为身份。请参阅下面的小提琴以获取更多信息。

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

或者,您可以做的是让 tblMobileForms 有它自己的单独代理键,并有一个与 tblForms 表不同的 FK 列。

于 2012-10-25T14:47:38.960 回答
1

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

在我的小提琴中,该tblForms表包含上 60 年代的 ID。在子表中运行INSERTid 会添加一条 id 为 1 的记录,该记录在父表中不存在。

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

于 2012-10-25T14:45:49.107 回答
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未指定的插入行。如果其中没有空闲 ID,tblForms则触发器将引发错误,因此保持 1 对 1 的关系(由于 tblMobileForms.fm_id 也是 PK,因此无论如何都会引发错误)。

注意,这要求 tblForms.fm_ID 只是一个 int 列,而不是标识。

于 2012-10-25T15:12:37.770 回答