gpt4 book ai didi

mysql - 我应该标准化发票数据库表集吗?

转载 作者:行者123 更新时间:2023-11-29 14:22:22 25 4
gpt4 key购买 nike

我正在构建一个在线发票平台,但正在努力解决标准化的概念,因为它与每张发票上的行项目相关。我的表结构如下:

雇主

  • ID(PK、自动增量)
  • empID(整数)
  • 名称(varchar)
  • (其他不相关字段)

成员(member)

  • ID(PK、自动增量)
  • empID(外籍雇主)
  • memberid(整数)
  • 名称(varchar)
  • (其他不相关字段)

计划

  • planid(PK,自动增量)
  • 描述(varchar)
  • 价格(十进制)

成员(member)计划

  • ID(PK、自动增量)
  • 成员(member) ID(外籍成员(member))
  • planid(FK 到计划,int)
  • 状态(整数,1 表示事件,0 表示非事件)
  • 开始(日期时间)
  • end(日期时间,可以为空)

发票

  • invoiceid(PK,自动增量)
  • empID(外籍雇主)
  • 日期(日期时间)
  • 小计(十进制)
  • 增值税(十进制)
  • previous_owed(十进制)
  • 状态(整数)

发票项目

  • ID(PK、自动增量)
  • invoiceid(发票的 FK)
  • memberid(外籍成员(member))
  • planid(FK 到计划)
  • 价格(十进制)

成员属于雇主团体。雇主代表其成员(member)缴纳会费。每个成员可以选择多个计划,因此发票将包含行项目(成员 ID、名称)以及每个成员的子项目(计划 ID、描述、价格)。每个成员的所有计划的总和会汇总在一起并向雇主开具发票以供在线审核。

我希望能够随时返回并根据所选日期生成发票。目前,我基本上每月都会导入所有现有member_plans 的快照,导入invoice_items 并分配invoiceid。这似乎复制了很多数据(尽管对于真正的快照来说可能是必要的,因为 member_plans 中的开始和结束日期并不能真正指示某些因素,即结束日期可以在任何时间点更改“就好像“由于退款或法律问题,该成员(member)在某个特定时间段内从未活跃过。

是否有正确/有效的方法来标准化发票_项目表,或者我列出的方法确实是唯一正确的方法?无论如何,我们的计划是在 7 个月后归档发票,因此虽然表大小值得关注,但它并不是一个永无休止的增长表。

最佳答案

以下是发票项目的一些小设计问题。

ID (PK, autoincrement)
invoiceid (FK to invoices)
memberid (FK to members)
planid (FK to plans)
price (decimal)

ID 是不必要的,并且没有任何其他更改,是一个损坏的代理键。它已损坏,因为作为代理,它应该取代自然键,但您尚未创建自然键。 (代孕这个词的本质意思是“取代”。例如,代孕母亲取代了亲生母亲。)

让我们看一些伪 SQL。

create table invoice_items (
invoiceid integer not null,

-- Traditionally, line items are numbered sequentially starting at 1
-- for each invoice. Your traditions might be different. "Some sane value"
-- prevents you from sending someone a 10,000 line invoice by mistake.
-- See below (way below) for implementing CHECK() constraints in MySQL.
-- A constraint that says, "Start with 1, no gaps" would be nice. I'll
-- let you code that one. ;)
line_item_num integer not null check (line_item_num >= 1 and
line_item_num <= [some sane value]),

memberid integer not null,
planid integer not null,

-- Choose the range to fit your application, and to prevent egregious mistakes.
price decimal(...) not null check (price between -10000 and 10000),

-- This constraint implements the traditional idea of invoice line items.
primary key (invoiceid, line_item_num),

-- This constraint prevents billing a single member plan twice on one invoice.
-- It might need to be dropped. For example, if you invoice one line item for
-- the base price for a member plan, then also invoice one line item for
-- a discount to the same member plan, you'd need to drop this constraint.
unique (invoiceid, memberid, planid),

foreign key (invoiceid) references invoices (invoiceid),

-- This foreign key needs to reference the single table member_plans, not the
-- two tables members and plans. Referencing the single table prevents you from
-- invoicing a member for a plan that member hasn't chosen.
foreign key (memberid, planid) references member_plans (memberid, planid)
);

您提到“描述”作为此表的一部分,但将其排除在列列表之外。我也把它遗漏了。

检查 MySQL 中的约束

MySQL 不支持 CHECK() 约束。在某些情况下,将 CHECK() 约束实现为对另一个表的外键引用是很实用的。例如,实现我上面为 line_item_num 编写的 CHECK() 约束作为对行项目编号表的外键引用是很实用的。

在其他情况下,外键引用可能不实用。例如,价格范围可能太大,您无法以这种方式实现。 -10000.00 到 +10000.00 的范围需要几百万行。一种替代方法是使用触发器。在最坏的情况下,您可能必须依赖应用程序代码和异常报告。 (偶尔会运行异常报告来搜索漏掉的无效值。)

其他一些需要注意的事情。 。 .

发票 ID 号通常不是自动递增的整数。自动递增整数可以有间隙。会计师讨厌差距。迟早,他们会想知道发票编号 10156 发生了什么,并且他们喜欢听到“这可能只是 dbms 由于事务失败或其他原因而丢弃的数字。”

如果雇主.empID 是唯一的,则添加具有 ID 号的另一列不会使其更加唯一。 members.memberid 也是如此。请参阅cargo cult programming .

关于mysql - 我应该标准化发票数据库表集吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11564757/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com