Sql 服务器在事务中向 table 添加多个外键约束

Sql Server adding multiple foreign key constraints to a table within a transaction

我正在编写一个 sql 服务器脚本来创建一些 table,然后更改 table 以添加我认为必要的外键约束。

我正在尝试将此脚本包装到一个事务中,以确保要么什么都不做,要么一切都完成。我遇到的问题是,当尝试在相同的 table.

中添加外键约束时,脚本似乎给我一个错误

到目前为止我尝试过的:

ALTER TABLE UoMConversion
ADD CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMFrom FOREIGN KEY(UoMFrom)
    REFERENCES UnitOfMeasure(UoMID)
    ON DELETE CASCADE;
ALTER TABLE UoMConversion
ADD CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMTo FOREIGN KEY(UoMTo)
    REFERENCES UnitOfMeasure(UoMID)
    ON DELETE CASCADE;

ALTER TABLE UoMConversion
ADD CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMFrom FOREIGN KEY(UoMFrom)
    REFERENCES UnitOfMeasure(UoMID)
    ON DELETE CASCADE,
    CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMTo FOREIGN KEY(UoMTo)
    REFERENCES UnitOfMeasure(UoMID)
    ON DELETE CASCADE;

我希望两者都能奏效。但是,脚本和 DDL 被包装到一个带有 Try and Catch 的事务中。

    BEGIN TRANSACTION CreateTables 
    BEGIN TRY
    USE ProductDB
    
        CREATE TABLE UnitOfMeasure(
            UoMID int not null identity(1,1) primary key,
            UoMDescription varchar(255) not null,
            UoMAbbreviation varchar(10) not null,
            UoMCategoryID int   -- FK__UnitOfMeasure__UnitOfMeasureCategory
        );
        
        
        CREATE TABLE UnitOfMeasureCategory(
            UoMCategoryID int not null identity(1,1) primary key,
            UoMCategory varchar(100) not null
        );
        
        CREATE TABLE UoMConversion (
            UoMConversionID int not null identity(1,1) primary key,
            UoMFrom int not null,   -- FK__UoMConversion__UnitOfMEasure__UoMFrom
            UoMTo int not null,     -- FK__UoMConversion__UnitOfMeasure__UoMTo
            Factor decimal(5),
            UoMCategoryID int       -- FK__UoMConversion__UnitOfMeasureCategory
        );
        ALTER TABLE UoMConversion
          ADD CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMFrom FOREIGN KEY(UoMFrom)
        REFERENCES UnitOfMeasure(UoMID)
        ON DELETE CASCADE;
        ALTER TABLE UoMConversion
           ADD CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMTo FOREIGN KEY(UoMTo)
            REFERENCES UnitOfMeasure(UoMID)
            ON DELETE CASCADE;
END TRY
 
BEGIN CATCH  
    SELECT   
        ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_SEVERITY() AS ErrorSeverity  
        ,ERROR_STATE() AS ErrorState  
        ,ERROR_PROCEDURE() AS ErrorProcedure  
        ,ERROR_LINE() AS ErrorLine  
        ,ERROR_MESSAGE() AS ErrorMessage;  
  
 IF @@ERROR > 0  
    ROLLBACK TRANSACTION;  
 END CATCH;  
  
 SELECT @@TRANCOUNT AS OpenTransactions


 COMMIT TRANSACTION;  

另外,当我删除两个外键语句之一时,错误消失了。需要注意的重要一点是 table 不存在于数据库中。所以当 运行 这个脚本在数据库中没有现有的 table 或关系等。

我得到的错误是:

这意味着在 table 上添加 PRIMARY KEY 约束时会遇到此错误,其中指定为 PRIMARY KEY 的列定义为 NULLABLE。事实并非如此,因为:

table 字段 UoMFrom 和 UoMTo 都是使用非空 属性 创建的,正如您将在上面的脚本中看到的那样。

有没有在事务中创建多个外键约束而不会出现此错误的方法?

如有任何帮助或建议,我们将不胜感激!提前致谢。

使用的软件:

Microsoft SQL Server Management Studio                      14.0.17289.0
Microsoft Analysis Services Client Tools                    14.0.1016.283
Microsoft Data Access Components (MDAC)                     10.0.19041.1
Microsoft MSXML                                             3.0 6.0 
Microsoft Internet Explorer                                 9.11.19041.0
Microsoft .NET Framework                                    4.0.30319.42000
Operating System                                            6.3.19043

这里不用TRY/CATCH。只需在交易中设置 XACT_ABORT 和 运行 批次。

USE ProductDB

SET XACT_ABORT ON 
BEGIN TRANSACTION 
    
CREATE TABLE UnitOfMeasure(
    UoMID int not null identity(1,1) primary key,
    UoMDescription varchar(255) not null,
    UoMAbbreviation varchar(10) not null,
    UoMCategoryID int   -- FK__UnitOfMeasure__UnitOfMeasureCategory
);
        
        
CREATE TABLE UnitOfMeasureCategory(
    UoMCategoryID int not null identity(1,1) primary key,
    UoMCategory varchar(100) not null
);
        
CREATE TABLE UoMConversion (
    UoMConversionID int not null identity(1,1) primary key,
    UoMFrom int not null,   -- FK__UoMConversion__UnitOfMEasure__UoMFrom
    UoMTo int not null,     -- FK__UoMConversion__UnitOfMeasure__UoMTo
    Factor decimal(5),
    UoMCategoryID int       -- FK__UoMConversion__UnitOfMeasureCategory
);
ALTER TABLE UoMConversion
    ADD CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMFrom FOREIGN KEY(UoMFrom)
REFERENCES UnitOfMeasure(UoMID) ON DELETE CASCADE;

ALTER TABLE UoMConversion
    ADD CONSTRAINT FK__UoMConversion__UnitOfMEasure__UoMTo FOREIGN KEY(UoMTo)
    REFERENCES UnitOfMeasure(UoMID) ON DELETE CASCADE;

COMMIT TRANSACTION;  

您将看到所有 返回的错误消息:

Msg 1785, Level 16, State 0, Line 30
Introducing FOREIGN KEY constraint 'FK__UoMConversion__UnitOfMEasure__UoMTo' on table 'UoMConversion' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Msg 1750, Level 16, State 1, Line 30
Could not create constraint or index. See previous errors.

您可以通过从至少一个外键中删除 ON DELETE CASCADE 来解决。