我有一张“收据”表。我有列 customer_id (谁有收据)和收据号。对于每个客户,receipt_number 应从 1 开始,并且是一个序列。这意味着 customer_id 和receipt_number 将是唯一的。我怎样才能优雅地做到这一点。我可以将内置序列功能与 CREATE SEQUENCE 或类似功能一起使用吗?看来我必须为每个客户创建一个序列,这当然不是一个优雅的解决方案。
编辑:必须有一种线程安全和白痴安全的方法来做到这一点。这应该是一个非常简单/常见的需求。
SEQUENCE 不保证没有间隙。例如,一笔交易可能会生成一个新数字,然后中止(由于错误或电源故障或其他原因......)。然后,下一笔交易将盲目地获得下一个数字,而不是“丢失”的数字。
如果您的客户端应用程序首先不依赖于“无间隙”假设,那就最好了。但是,您可以像这样最小化间隙:
SELECT MAX(receipt_number) FROM receipts WHERE customer_id = :ci
-
INSERT INTO receipts(customer_id, receipt_number) VALUES (:ci, aboveresult+1)
,或者只插入 1 ifstep 1返回 NULL。
- If step 2 returned a PK violation*, retry from the beginning.
* Because a concurrent transaction has gone through the same process and committed.
只要仅添加行而不是删除行,即使在并发环境中,也应该可以防止出现任何间隙。
顺便说一句,你可以“压缩”步骤 1 和 2像这样:
INSERT INTO receipts (customer_id, receipt_number)
SELECT :ci, COALESCE(MAX(receipt_number), 0) + 1
FROM receipts
WHERE customer_id = :ci;
[SQL 小提琴] http://sqlfiddle.com/#!1/d366f/3
PK {customer_id,receipt_number} 下面的索引应确保有效满足此查询的 SELECT 部分。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)