代码之家  ›  专栏  ›  技术社区  ›  dudeNumber4

无法将TSQL输出与普通外键约束一起使用?

  •  6
  • dudeNumber4  · 技术社区  · 14 年前

    以下代码段失败,出现错误:

    OUTPUT INTO子句的目标表“dbo.forn”不能位于(主键、外键)关系的任一侧。找到引用约束'FK\u forn\u prim'

    我只能通过禁用外键约束来使用输出?如何做到这一点?

    IF OBJECT_ID ('dbo.forn') IS NOT NULL
    begin
        alter table dbo.forn drop constraint FK_forn_prim
        DROP TABLE dbo.forn;
    end
    IF OBJECT_ID ('dbo.prim') IS NOT NULL
        DROP TABLE dbo.prim;
    go
    
    CREATE TABLE dbo.prim (c1 int PRIMARY KEY);
    CREATE TABLE dbo.forn (c1 int CONSTRAINT FK_forn_prim FOREIGN KEY (c1) REFERENCES dbo.prim(c1));
    go
    
    INSERT INTO dbo.prim
        OUTPUT inserted.c1 INTO dbo.forn
    SELECT 1;
    
    4 回复  |  直到 12 年前
        1
  •  2
  •   etoisarobot    14 年前

    根据 technet

    无法保证将更改应用于表的顺序与将行插入输出表或表变量的顺序是一致的。

    基于此,有许多限制,其中包括上面遇到的限制,但是如果您只想在第二个表中记录插入的值,我不明白为什么需要上面定义的外键关系。

        IF OBJECT_ID ('dbo.forn') IS NOT NULL
    begin
        alter table dbo.forn drop constraint FK_forn_prim
        DROP TABLE dbo.forn;
    end
    IF OBJECT_ID ('dbo.prim') IS NOT NULL
        DROP TABLE dbo.prim;
    go
    
    CREATE TABLE dbo.prim (c1 int PRIMARY KEY);
    CREATE TABLE dbo.forn (c1 int CONSTRAINT FK_forn_prim FOREIGN KEY (c1) REFERENCES dbo.prim(c1));
    go
    
    CREATE TRIGGER InsertRecord
       ON  dbo.Prim
       AFTER Insert
    AS 
    BEGIN
        SET NOCOUNT ON;
        Insert into dbo.forn Select * from inserted;
    END
    GO
    
    INSERT INTO dbo.prim SELECT 1;
    
        2
  •  15
  •   HLGEM    14 年前

    通常输出到一个表变量或临时表,然后用它插入到最终的表中。

        3
  •  4
  •   Jeremy Jarrell    12 年前

    您是对的,output语句在外键约束下的表上不起作用。

    另一个选项是在插入数据时临时禁用约束。虽然这不应该成为标准,但对于一次性加载的数据来说效果很好。

    ALTER TABLE dbo.forn
    NOCHECK CONSTRAINT FK_forn_prim
    GO
    
    INSERT INTO dbo.prim
        OUTPUT inserted.c1 INTO dbo.forn
    SELECT 1;
    
    ALTER TABLE dbo.forn
    CHECK CONSTRAINT FK_forn_prim
    GO
    
        4
  •  1
  •   Community rohancragg    7 年前

    ( 不建议这样做。

    但是,我发现,如果禁用外键约束并使用 NOCHECK/CHECK . 换句话说:一个disable-enable循环就足以使FK约束“不可见”,从而将输出转化为外键约束禁止。注意以下修改:

    IF OBJECT_ID ('dbo.forn') IS NOT NULL
    begin
        alter table dbo.forn drop constraint FK_forn_prim
        DROP TABLE dbo.forn;
    end
    IF OBJECT_ID ('dbo.prim') IS NOT NULL
        DROP TABLE dbo.prim;
    go
    
    CREATE TABLE dbo.prim (c1 int PRIMARY KEY);
    -- note change here:
    CREATE TABLE dbo.forn (c1 int );
    alter TABLE dbo.forn with nocheck add CONSTRAINT FK_forn_prim FOREIGN KEY (c1)     REFERENCES dbo.prim(c1);
    alter TABLE dbo.forn check CONSTRAINT FK_forn_prim ;
    -- end change
    go
    
    INSERT INTO dbo.prim
        OUTPUT inserted.c1 INTO dbo.forn
    select 1;
    

    以下操作失败(违反约束),因此您知道DRI仍在工作:

    INSERT INTO dbo.prim
        OUTPUT inserted.c1 + 1 INTO dbo.forn
    select 2;
    

    question 在这一点上,虽然还没有得到很好的接受。

    更新

    前面提到的问题是 answered

    alter TABLE dbo.forn check CONSTRAINT FK_forn_prim ;

    alter table dbo.forn with check check CONSTRAINT FK_forn_prim;