在关系数据库的 table 上,哪一个应该是首选 1:1,0 或可为空的字段?

Which one should be preferred 1:1,0 or nullable fields on one table on relational database?

我首先使用 Azure Sql 和实体框架代码。

我有TransactionTable。有buy/sellwithdrawaldepositfee

4种类型

例如,我需要 DepositCode 进行存款交易,但对于其他人,此列将为空。我还需要 ItemPriceItemAmount 用于 buy/sell 但对于其他类型它将为空。

例子TransactionTable

 public class Transaction
    {
        public long Id { get; set; }
        public decimal Amount { get; set; }
        public int Type { get; set; }
        public string DepositCode { get; set; }
        public decimal? ItemPrice { get; set; }
        public decimal? ItemAmount { get; set; }
        public string WithdrawalIban { get; set; }
    }

 public class Transaction
    {
        public long Id { get; set; }
        public decimal Amount { get; set; }
        public int Type { get; set; }
        public DepositTransaction DepositTransaction { get; set; }
        public WithdrawalTransaction BuyAndSellTransaction { get; set; }
        public WithdrawalTransaction WithdrawalTransaction { get;set; }
    }


 public class DepositTransaction
    {
        public long Id { get; set; }
        public Transaction Transaction { get; set; }
        public string DepositCode { get; set; }
    }


 public class WithdrawalTransaction
    {
        public long Id { get; set; }
        public Transaction Transaction { get; set; }
        public string WithdrawalIban { get; set; }
    }


 public class BuySellTransaction
    {
        public long Id { get; set; }
        public Transaction Transaction { get; set; }
        public decimal ItemPrice { get; set; }
        public decimal ItemAmount { get; set; }
    }

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<WithdrawalTransaction>()
        .HasRequired(wt => wt.Transaction)
        .WithOptional(tr => tr.WithdrawalTransaction);

        modelBuilder.Entity<DepositTransaction>()
      .HasRequired(db => db.Transaction)
      .WithOptional(tr=> tr.DepositTransaction);

        modelBuilder.Entity<BuySellTransaction>()
      .HasRequired(bs => bs.Transaction)
      .WithOptional(tr => tr.BuySellTransaction);

    }

应该首选哪一个?

如果可能,我更喜欢可为空的字段,这是 table 每个 class 层次结构 映射中的实现。使用这种方法,EF 会将所有事务对象存储在一个 table 中,并将使用鉴别器列来为您管理类型加载。那就是说我会按如下方式重构您的模型:

public abstract class Transaction
{
    public long Id { get; set; }
    public DateTime TransactionDate { get; set; }
}


public class DepositTransaction : Transaction
{
    public string DepositCode { get; set; }
}


public class WithdrawalTransaction : Transaction
{
    public string WithdrawalIban { get; set; }
}


public class BuySellTransaction : Transaction
{
    public decimal ItemPrice { get; set; }
    public decimal ItemAmount { get; set; }
}

您实际上只有三笔交易:buy/sell、deposit/withdrawal、手续费。买入和卖出的区别在于金额为正为买入,金额为负为卖出。存款和取款也是如此。

create table Transactions(
    ID         bigint identity primary key,
    XType      char( 1 ) not null, -- 'B': buy/sell, 'D': dep/with, 'F': fee
    Amount     money not null,
    constraint CK_Transaction_Type check( XType in( 'B', 'D', 'F' ),
    constraint UQ_Transaction_Type unique( ID, XType )
);

其他 tables(或子tables,如果你想这样想的话)看起来像这样:

create table BuySellTrans(
    TransID    bigint not null,
    TransType  char( 1 ) not null,
    ...,   -- other info regarding purchase or sale
    constraint CK_BuySellTrans_BuySellType check( TransType = 'B' )
    constraint FK_BuySellTrans_Trans foreign key( TransID, TransType )
        references Transactions( ID, XType )
);

至于代码,最好的方法可能是有一个抽象的超级 class 交易,其中包含 subclasses BuySell、DepositWithdrawal 和 Fee。我还会提供一些方便的视图,巧合的是,BuySell、DepositWithdrawal 和 Fee。这些视图将提供交易 table 与适当子 table 的联合数据集。视图上的触发器(您的系统允许)将大大简化应用程序代码,因为每个 subclass 将仅通过视图进行查询和操作。代码甚至不需要知道数据库中的物理布局。