No way to use TSQL Output with normal foreign key constraints?

前端 未结 4 1854
野的像风
野的像风 2021-01-18 06:30

The following snippet fails with error:

The target table \'dbo.forn\' of the OUTPUT INTO clause cannot be on either side of a (primary key, foreign ke

4条回答
  •  离开以前
    2021-01-18 06:46

    The documentation does indicate that the output table may not participate in foreign key constraints (or check constraints, nor may it have enabled triggers defined on it--but those cases aren't considered here). The Msg 332 error is the manifestation of that.

    (THIS IS NOT RECOMMENDED. See update below)

    However, I have found that this limitation is subverted if the foreign key constraint is disabled and re-enabled with NOCHECK/CHECK even after the constraint is re-enabled. In other words: one disable-enable cycle is enough to make the FK constraint "invisible" to the output-into-foreign-key-constraint prohibition. Note the modification below:

    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;
    

    The following fails (constraint violation) so you know the DRI is still working:

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

    Given the prohibition in the docs, I grant this seems dubious. I have a question pending on this point, though it hasn't been well-received.

    UPDATE

    The previously mentioned question was answered, and the new information invalidates this answer. Leaving this up as a warning to others, in case they stumble upon this seemingly fortuitous hole.

    The upshot is: alter TABLE dbo.forn check CONSTRAINT FK_forn_prim ; reenables the constraint but leaves it in an "untrusted" state, so it cannot be fully utilized by the SQL engine for index optimization and such. It is not recommended. The correct way to reenable is

    alter table dbo.forn with check check CONSTRAINT FK_forn_prim;
    

提交回复
热议问题