代码之家  ›  专栏  ›  技术社区  ›  Gabriel Sosa

这是一个好的会员支付数据库模式吗?

  •  3
  • Gabriel Sosa  · 技术社区  · 15 年前

    我正在做一个项目来管理会员资格和其他类型的付款,但主要是会员资格,所以我创建了一个多态模式。任何想法,改进,出于某种原因,我不完全相信这个模式。

    正如您将看到的,让月份、年份为空的想法是允许保存任何其他付款的记录

    CREATE TABLE IF NOT EXISTS `orders` (
      `id` int(11) NOT NULL auto_increment,
      `partner_id` int(11) NOT NULL,
      `status` enum('pending','accepted','cancelled','other') NOT NULL,
      `created_on` datetime NOT NULL,
      `concept` varchar(250) NOT NULL,
      `type` enum('membership','other') NOT NULL default 'membership',
      `source` enum('dineromail','casati','deposit','other') NOT NULL default 'dineromail',
      `notes` text NULL,
      `last_check_on` datetime default NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  ;
    
    
    CREATE TABLE IF NOT EXISTS `payments` (
      `id` int(11) NOT NULL auto_increment,
      `order_id` int(11) NOT NULL,
      `month` int(11) default NULL,
      `year` int(11) default NULL,
      `amount` float NOT NULL,
      PRIMARY KEY  (`id`),
      UNIQUE KEY `idx-order_id-month-year` (`order_id`,`month`,`year`)
    ) ENGINE=MyISAM ;
    
    
    CREATE TABLE IF NOT EXISTS `partners` (
      `id` int(10) unsigned NOT NULL auto_increment,
      `name` varchar(255) default NULL,
      `last_name` varchar(255) default NULL,
    
    ) ENGINE=MyISAM;
    
    6 回复  |  直到 15 年前
        1
  •  5
  •   Justin Yost    15 年前

    我还将包括一个日期时间戳的付款时收到,并可能标记,如果付款是完整或不完整的金额。

        2
  •  4
  •   Yishai    15 年前

    1. 在这种情况下,我会考虑把月份变成一个枚举。它当然可以消除所有的歧义,除非你需要在这个领域做数学计算(这是之前的那个)。

    2. 货币应该存储为十进制,而不是浮点数。如果不是的话,奇怪的圆形东西会悄悄地进来。

    3. 没有订单价格的概念。如果他们少付工资,你怎么知道少付了多少?

    4. (有点与3相关)您通常会将其视为发票和付款类型表示(即使您不开具发票),因此这意味着一笔付款可以表示多个订单,反之亦然,因此这意味着多对多关系。

    5. 你在乎他们怎么付吗?(支票、信用卡、现金等)

        3
  •  2
  •   spencer7593    15 年前

    另一个注意事项是,我们的约定是以单数形式命名实体表,与类名匹配。也就是说,我们命名一行(命名类的一个实例),而不是命名集合。我们要问的问题是,这个表中的一行代表一个什么?我们在类和表中使用这个单数名称。(考虑到反对意见,是的,我确实认识到其他开发人员和其他框架遵循“表名多元化”的惯例。Rails在多元化方面甚至足够聪明,可以从Person类生成“people”表。)

    `partner_id`
    `order_id`
    

    外键列的命名方式与我们命名它们的方式完全相同。对于外键列,我们遵循的约定是使用父表的名称,后跟_id。对于同一个表的多个关系,除了表名之外,我们还使用角色的名称,或者使用角色的名称代替表名。

    我还建议在数据库中添加外键约束定义,即使MyISAM引擎没有强制执行它们。

    在每个表的ID列上添加主键约束(在 partner 桌子

    使用unqiue索引识别自然键。

    • 每次订单一次全额付款

    这就是亚马逊似乎使用的模式。订单上可能会有奖金优惠券和信用卡,但当涉及到付款时,我只为订单支付一笔款项。

    另一种模式是使用帐户,并向帐户应用费用、贷项和付款。这是电话公司等公用事业公司常用的模式。这允许使用诸如当前余额和到期金额之类的概念。

        4
  •  2
  •   Community CDub    4 年前
    • 与十进制相同,而不是货币金额的浮动。
    • 订单金额在哪里?你怎么知道他们是否欠了钱?
    • payment_date payments 会让你摆脱 orders.last_check_on 赞成一种观点
    • payments.month payments.year 看起来很奇怪。如果这是一个会员制,我想你只需付现收现付。因此,6次付款将使您同时获得6个月的会员资格-从订单日期开始。没有必要跟踪付款的月份(否则,我支付第6个月和第7个月,而不是1-5个月,这意味着什么?)。

    type 枚举('成员资格','其他')

    允许月、年为空的想法是允许保存任何其他付款的记录

    我可能有点不对劲,但听起来你们好像在猜测未来的需求。如果是这样的话……不要这样做。没有一刀切的数据库模式——因此不要损害您正在为将来可能会或可能不会构建的应用程序构建的应用程序。

    Type 可为空的列通常会尖叫,表示您试图将不同的内容塞进同一个表中。

        5
  •  1
  •   smholloway thomasd    11 年前
    CREATE TABLE [dbo].PaymentLog(  
        TransactionNumber int IDENTITY(1,1) NOT NULL,  
        ReferenceID int NOT NULL,  
        ReferenceType varchar(20) NULL,  
        TransactionID int NULL,  
        CustomerID int NULL,  
        PaymentMethod char(4) NULL,  
        LogType varchar(20) NULL,  
        UserHostAddress varchar(20) NULL,  
        Content nvarchar(4000) NULL,  
        ReasonCode varchar(20) NULL ,  
        Flag nvarchar(20) NULL ,  
        Note nvarchar(200) NULL,  
        [InDate] [datetime] NOT NULL CONSTRAINT DF_PaymentLog_InDate DEFAULT (GETDATE()),    
        [InUser] [nvarchar](100) NULL,  
        CONSTRAINT PK_PaymentLog PRIMARY KEY CLUSTERED (  
            TransactionNumber  
        )   
    )
    GO
    
    CREATE NONCLUSTERED INDEX [IX_PaymentLog_ReferenceID] ON [dbo].PaymentLog (  
        ReferenceID ASC  
    ) WITH FILLFACTOR = 90  
    GO
    
        6
  •  0
  •   phpfour phpfour    15 年前

    另外,我会将源代码放在另一个表中,因为当应用程序增长时,您可能需要添加一些源代码。