在SQL中设计多种类型的支付模式?

在SQL中设计多种类型的支付模式?,sql,database,database-design,rdbms,Sql,Database,Database Design,Rdbms,我有一个付款系统,我可以为一个订单做两种类型的付款 在线移动支付 离线-现金/支票 我已经记下了4个表,我只列出了重要的列,并不是为了简单 List of table Names Payment CashPaymentDetails ChequePaymentDetails MobilePaymentDetails Schema Details CashPaymentDetails cash_id int cash_amount decimal(18,2) ChequePaymentDe

我有一个付款系统,我可以为一个订单做两种类型的付款

  • 在线移动支付
  • 离线-现金/支票
  • 我已经记下了4个表,我只列出了重要的列,并不是为了简单

    List of table Names
    
    Payment
    CashPaymentDetails
    ChequePaymentDetails
    MobilePaymentDetails
    
    Schema Details
    
    CashPaymentDetails
    cash_id int
    cash_amount decimal(18,2)
    
    ChequePaymentDetails
    cheque_id int
    cheque_amount decimal(18,2)
    cheque_type
    
    MobilePaymentDetails
    mobile_id int
    mobile_amount decimal(18,2)
    
    Payment
    payment_id int
    payment_amount  decimal(18,2)
    fk_cash_id int (foreign key reference to CashPaymentDetails table)
    fk_cheque_id (foreign key reference to ChequePaymentDetails table)
    fk_mobile_id (foreign key reference to MoblePaymentDetails table)
    
    用户可以使用现金/支票/手机,只有一种支付模式,这使得我的两个外键为空,我觉得这是开销,因为如果继续下去,我有10种不同类型的支付方式,9个Fk引用将为空

    付款

    Payment_id payment_amount fk_cash_id fk_cheque_id fk_mobile_id
    1 300 1 NULL NULL
    2 200 NULL 1 NULL
    3 400 NULL NULL 1
    
    创建此模式的最佳设计应该是什么?

    您的设计很好(不是唯一的选择,但很好)。我将向表中添加一个约束,以确保实现一种付款类型(确切地说是一种付款类型):

    alter table payment
        add constraint chk_one_payment
            check ((fk_cash_id is not null and fk_cheque_id is null and fk_mobile_id is null) or
                  (fk_cash_id is null and fk_cheque_id is not null and fk_mobile_id is null) or
                  (fk_cash_id is null and fk_cheque_id is null and fk_mobile_id is not null)
                 );
    
    还有其他的方法来表示一种关系。例如,您可以:

    • PaymentType(现金、支票、手机中的一种)
    • 付款额
    • 检查类型(如适用)

    不同类型的付款具有几乎相同的列,因此这在您的情况下是非常合理的。对于某些关系,不同的类型有非常不同的列,并且希望位于各自的表中。

    为PaymentMethod创建表,并在PaymentMethod中引用其PK,然后根据PaymentMethod,您可以在相应的PaymentMethod表中进行适当的输入。我还在[CashPaymentDetails]、[ChequePaymentDetails]和[MobilePaymentDetails]表中添加了付款id

    Schema Details
    
    [PaymentMethods]
    Payment_Method_id int
    Payment_Method_Description varchar(50)  --  ("cash", "cheque", "mobile" etc)
    
    [Payment]
    Payment_id int
    Payment_Method_id int
    payment_amount  decimal(18,2)
    
    
    [CashPaymentDetails]
    cash_id int
    payment_id int
    cash_amount decimal(18,2)
    
    [ChequePaymentDetails]
    cheque_id int
    payment_id int
    cheque_amount decimal(18,2)
    cheque_type
    
    [MobilePaymentDetails]
    mobile_id int
    payment_id int
    mobile_amount decimal(18,2)
    
    我的建议是这样的。 在付款表上,删除所有外键并添加这两个字段

    processor_type enum['bank', 'cheque', 'card']
    transaction_id fk to the processor table. 
    
    这样,每次更新/添加新的处理器时,只需更新枚举,使其接受新的支付处理器集。事务id是相应表的外键,具体取决于处理器类型

    如果您使用的是laravel,则可以利用多态关系
    这是我的建议

    为什么是多张桌子。我会坚持使用PaymentType、ReferenceNbr和Amount@JohnCappelletti多个表,因为支票有一些现金没有的信息(支票类型、日期、IFSC),而手机有现金/支票没有的transferRefNo。不同的表可以帮助我有效地分离相关信息。公平地说,你比任何人都更了解你的数据和要求。如果我添加10种不同的付款方式,那么9个Fk列将为空,这会增加开销。@user614978。是的,但这不是您问的问题。您可能希望将Payment\u Method\u ID添加到各个详细信息表中,并将其与Payment\u ID一起用作Payment表的外键(将Payment\u Method\u ID和Payment\u ID包含在唯一索引中以实现此目的)。然后就不可能为定义为现金等的付款插入支票明细。