用随机数替换序列

Ulf*_*lfR 12 sql random postgresql

我想用我自己定制的id生成器替换我在postgresql数据库中用于id的一些序列.生成器将生成一个随机数,最后带有一个checkdigit.所以这:

SELECT nextval('customers')
Run Code Online (Sandbox Code Playgroud)

会被这样的东西取代:

SELECT get_new_rand_id('customer')
Run Code Online (Sandbox Code Playgroud)

然后该函数将返回一个数值,例如:[1-9][0-9]{9}最后一个数字是校验和.

我担心的是:

  1. 我如何使事物成为原子
  2. 我如何避免两次返回相同的id(这可以通过尝试将其插入具有唯一约束的列中来捕获,但是我认为它迟到了)
  3. 这根本不是一个好主意吗?

注1:我不想使用uuid,因为它要与客户沟通,10个数字比36个字符uuid更容易沟通.

注意2:该函数很少被调用,SELECT get_new_rand_id()但会在id-column上被指定为默认值而不是nextval().

编辑:好的,下面的讨论很好!以下是对原因的一些解释:

  1. 那么为什么我会用这种方式过度复杂呢?purpouse是隐藏客户的主键.

    我给每个新客户一个唯一的customerId(在db中生成序列号).由于我与客户沟通该号码,我的竞争对手监控我的业务是一项相当简单的任务(还有其他数字,例如发票nr和订单nr具有相同的属性).正是这种监控我想更加努力(注意:并非不可能,但更难).

  2. 为什么是校验位?

    在有任何关于隐藏序列号的讨论之前我添加了一个checkdigit到ordernr,因为在制作中的某些点有klumbsy手指,我的想法是这将是一个很好的做法,以保持在未来.

在阅读完讨论后,我当然可以看到我的方法不是解决问题的最佳方法,但我对如何解决它没有其他好处,所以请在这里帮助我.

  1. 我应该添加一个额外的列,我将我公开的ID放在客户面上,并将串口作为主键吗?
  2. 如何以健全有效的方式生成要公开的id?
  3. 是否必须使用checkdigit?

int*_*tgr 18

为了从串行生成唯一且随机的标识符,使用密码可能是个好主意.由于它们的输出是双射的(输入和输出值之间存在一对一的映射) - 与哈希不同,您不会发生任何冲突.这意味着您的标识符不必像哈希一样长.

大多数加密密码在64位或更大的块上工作,但PostgreSQL wiki有一个示例PL/pgSQL过程,用于"非加密"密码函数,该函数适用于(32位)int类型.免责声明:我自己没有尝试过使用此功能.

要将它用作主键,请从Wiki页面运行CREATE FUNCTION调用,然后在表上执行:

ALTER TABLE foo ALTER COLUMN foo_id SET DEFAULT pseudo_encrypt(nextval('foo_foo_id_seq')::int);
Run Code Online (Sandbox Code Playgroud)

瞧!

pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> insert into foo (foo_id) values(default);
pg=> select * from foo;
  foo_id   
------------
 1241588087
 1500453386
 1755259484
(4 rows)
Run Code Online (Sandbox Code Playgroud)