以下是 invoice_items 的一些小设计问题。
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 丢弃的数字”。
如果employees.empID 是唯一的,添加另一个带有ID 号的列并不会使其更加唯一。members.memberid 也是如此。请参阅货物崇拜编程。