postgresql - 如何在一个表中创建多个序列?

标签 postgresql database-design postgresql-9.1 database-sequence

我有一张“收据”表。我有列 customer_id(谁有收据)和 receipt_number。每个客户的 receipt_number 应该从 1 开始,并且是一个序列。这意味着 customer_id 和 receipt_number 将是唯一的。我怎样才能优雅地做到这一点。我可以将内置序列功能与 CREATE SEQUENCE 或类似功能一起使用吗?看来我必须为每个客户创建一个序列,这当然不是一个优雅的解决方案。

编辑:必须有一个线程安全和白痴安全的方法来做到这一点。这应该是一个非常简单/常见的需求。

最佳答案

SEQUENCE 不保证没有间隙。例如,一项交易可能会生成一个新数字然后中止(由于错误或电源故障或其他原因......)。下一笔交易将盲目地获得下一个数字,而不是“丢失”的数字。

如果您的客户端应用程序首先不依赖于“无间隙”假设,那将是最好的。但是,您可以像这样最大限度地减少差距:

  1. SELECT MAX(receipt_number) FROM receipts WHERE customer_id = :ci
  2. INSERT INTO receipts(customer_id, receipt_number) VALUES (:ci, aboveresult+1),或者如果返回 step 1 则只插入 1空。
  3. 如果第 2 步返回 PK 违规*,请从头重试。

* 因为并发事务经历了相同的过程并提交。

只要行只是添加而不是删除,这应该可以防止任何间隙,即使在并发环境中也是如此。


顺便说一句,您可以像这样“压缩”步骤 1 和 2:

INSERT INTO receipts (customer_id, receipt_number)
SELECT :ci, COALESCE(MAX(receipt_number), 0) + 1
FROM receipts
WHERE customer_id = :ci;

[SQL Fiddle]

PK {customer_id, receipt_number} 下的索引应确保有效满足此查询的 SELECT 部分。

关于postgresql - 如何在一个表中创建多个序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12746106/

相关文章:

node.js - Postgres 动态创建监听器

postgresql - 错误 : there is no unique constraint matching given keys for referenced table "abteilung"

mysql - 哪种数据库方案在性能方面更好?

mysql - 数据库内存::MySql Innodb 空字段与非空字段 - varchar 或 text 分配多少存储内存

postgresql-9.1 - 如何显示 PostgreSQL 系统变量

sql - Order By character varying time strings?

postgresql - 检测postgres中的特殊字符

postgresql - 将表格中的两行合并为一行

java - 如何使用TestNG编写集成测试来检查JAVA中是否抛出异常?

Python Bookshelf 应用程序在使用 postgresql 云 SQL DB 部署到 GCP 时出错