你已经有了数据库,也有了表。甚至你已经往这些表里塞了数据。现在,是时候考虑一下这些数据的完整性了。
在每个schema里建表的时候,系统已经自动帮你加了指向本schema其他表的foreign keys(外键)。现在你需要把不同schema的表也连起来——加上跨schema的外键。
比如,order schema里的order表要关联到user schema里的account表的用户。你得给这个表加个外键。SQL大概长这样:
ALTER TABLE "order".order
ADD CONSTRAINT fk_order_user
FOREIGN KEY (user_id)
REFERENCES "user".account(id)
ON DELETE RESTRICT;
外键清单
一共要加40个外键,哈哈 :)
product schema:
[product].review.user_id → [user].account.id
商品的评论要和写评论的用户关联。
[product].question.user_id → [user].account.id
只有注册用户才能提问商品。
[product].answer.user_id → [user].account.id
回答也是属于用户的。
order schema:
[order].order.user_id → [user].account.id
下单的用户——必须是注册用户。
[order].order_item.product_id → [product].product.id
订单项必须指向具体的商品。
[order].order_item.variant_id → [product].variant.id
如果选了商品的variant,那它必须存在。但variant可能被删(那字段就变成NULL)。
[order].cart.user_id → [user].account.id
购物车属于某个用户。
[order].cart_item.product_id → [product].product.id
购物车里的商品必须是有效商品。
[order].cart_item.variant_id → [product].variant.id
选中的variant要存在,如果被删了——字段就变成NULL。
logistics schema:
[logistics].inventory.variant_id → [product].variant.id
variant可能被删(比如下架了)。
[logistics].inventory_movement.product_id → [product].product.id
仓库的任何操作都要关联真实商品。
[logistics].inventory_movement.variant_id → [product].variant.id
库存变动也可以针对某个variant。
[logistics].stock_level.product_id → [product].product.id
库存水平是针对现有商品设定的。
[logistics].transfer.product_id → [product].product.id
调拨只能针对真实存在的商品。
[logistics].transfer.variant_id → [product].variant.id
variant可能被删。
[logistics].package.order_id → [order].order.id
每个包裹都要和具体订单关联。
payment schema:
[payment].payment_transaction.order_id → [order].order.id
支付交易总是关联订单。
[payment].invoice.order_id → [order].order.id 发票是针对订单开的。
[payment].billing_address.user_id → [user].account.id
账单地址属于用户。
[payment].wallet.user_id → [user].account.id
钱包是用户唯一的。
marketing schema:
[marketing].discount.product_id → [product].product.id
折扣可以绑定到某个商品。
[marketing].discount.category_id → [product].category.id
折扣也可以绑定到商品分类。
[marketing].discount.brand_id → [product].brand.id
品牌折扣。
[marketing].promo_usage.user_id → [user].account.id
只有注册用户能用优惠码。
[marketing].featured_product.product_id → [product].product.id
首页推荐商品必须存在。
[marketing].referral_use.referrer_id → [user].account.id
邀请人——必须是用户。
[marketing].referral_use.referee_id → [user].account.id
被邀请人——也必须是用户。
support schema:
[support].support_ticket.user_id → [user].account.id
每个工单都是用户创建的。
[support].support_ticket.category_id → [support].ticket_category.id
工单分类可以被删,工单还在。
[support].ticket_message.sender_id → [user].account.id
消息是用户发的(或者是agent,如果他们也在user.account里)。
[support].support_agent.user_id → [user].account.id
客服agent——也是用户。
[support].ticket_status_log.changed_by → [user].account.id
记录是谁改了状态(用户或员工)。
content schema:
[content].article.author_id → [user].account.id
文章是注册用户写的。
[content].media.uploaded_by → [user].account.id
谁上传的媒体(可能被删)。
[content].content_revision.author_id → [user].account.id
谁做了修改(可能被删)。
注意
只要能用ON DELETE SET NULL的地方都建议用,这样删掉某个实体时,关联信息不会全丢。
如果是通过"target_type/target_id"这种方式关联(比如user.comment),SQL层面没法加外键,这种关联只能靠应用层控制。
这个清单覆盖了SQL层面保证基础数据完整性的主要跨schema关联。
包含解决方案的文件。
GO TO FULL VERSION