Sql 用随机数代替序列
我想用我自己定制的id生成器替换我在postgresql数据库中用于id的一些序列。生成器将生成一个末尾带有校验位的随机数。因此:Sql 用随机数代替序列,sql,postgresql,random,Sql,Postgresql,Random,我想用我自己定制的id生成器替换我在postgresql数据库中用于id的一些序列。生成器将生成一个末尾带有校验位的随机数。因此: SELECT nextval('customers') 将被以下内容取代: SELECT get_new_rand_id('customer') 然后,该函数将返回一个数值,例如:[1-9][0-9]{9},其中最后一个数字是校验和 我关注的是: 我如何使它原子化 如何避免两次返回相同的id(尝试将其插入到具有唯一约束的列中会发现这一点,但我认为这太晚了) 这是
SELECT nextval('customers')
将被以下内容取代:
SELECT get_new_rand_id('customer')
然后,该函数将返回一个数值,例如:[1-9][0-9]{9}
,其中最后一个数字是校验和
我关注的是:
选择get\u new\u rand\u id()
调用,而是在id列上指定为默认值,而不是nextval()
编辑:好的,下面的讨论很好!以下是一些原因的解释:
你最好的选择可能是某种形式的散列函数,然后在末尾添加一个校验和。我在你的问题上添加了我的评论,然后意识到我应该更好地解释自己。。。我道歉 用户可以看到第二个键,而不是主键。该密钥可以使用主密钥作为您描述的哈希函数的种子,并且是用于查找的密钥。该键将由插入后的触发器生成(这比试图确保操作的原子性要简单得多),并且 这是你与客户分享的关键,而不是PK。我知道,对于PKs是否对用户应用程序不可见存在争议(尽管我不明白为什么)。现代数据库设计实践和我的个人经验似乎都表明PKs不应该对用户可见。他们倾向于赋予他们意义,随着时间的推移,这是一件非常糟糕的事情——不管他们的钥匙中是否有校验位 您的连接仍将使用PK完成。这另一个生成的密钥只用于客户端查找。他们是脸,PK是勇气 希望有帮助
编辑:FWIW,关于数据库设计中的“对”或“错”,几乎没有什么可说的。有时它归结为一种选择。我认为你面临的选择将更好地服务于单独的PK和创建一个次要的关键-就是这样。我认为你已经把这件事复杂化了。为什么不让数据库做它最擅长的事情,让它考虑原子性并确保相同的id不会被使用两次呢?为什么不使用postgresql串行类型并获取自动生成的代理主键,就像SQL Server或DB2中的整数标识列一样?在列中使用该选项。此外,它将比用户定义的函数更快 我同意隐藏此代理主键并使用公开的次键(具有唯一约束)在接口中查找客户端 您使用序列是因为需要跨多个表使用唯一标识符吗?这通常表明您需要重新考虑表的设计,这几张表可能应该组合成一张表,并使用自动生成的代理主键
另请参见如果您不经常使用此功能(您不是每秒钟都有一个新客户,是吗?),则可以只获取一个随机数,然后尝试插入记录。只要准备好在唯一约束冲突导致插入失败时,使用另一个数字重试插入即可
我会使用1000000到999999的数字(900000个相同长度的可能数字),并使用检查数字。2个校验位会更好,因为它们可以消除99%的人为错误,而不是9%。对于从序列中生成唯一且随机的标识符,使用密码可能是一个好主意。由于它们的输出是双射的(输入值和输出值之间有一对一的映射)与哈希不同,您将不会有任何冲突。这意味着您的标识符不必像散列一样长 大多数加密密码可用于64位或更大的块,但PostgreSQL wiki有一个可用于(32位)
int
type的函数。免责声明:我本人没有尝试过使用此功能
要将其用于主键,请从wiki页面运行CREATE函数调用,然后在空表上执行以下操作:
ALTER TABLE foo ALTER COLUMN foo_id SET DEFAULT pseudo_encrypt(nextval('foo_foo_id_seq')::int);
瞧
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)
如何生成随机且唯一的ID是一个有用的问题-但是您需要