Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 用随机数代替序列_Sql_Postgresql_Random - Fatal编程技术网

Sql 用随机数代替序列

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(尝试将其插入到具有唯一约束的列中会发现这一点,但我认为这太晚了) 这是

我想用我自己定制的id生成器替换我在postgresql数据库中用于id的一些序列。生成器将生成一个末尾带有校验位的随机数。因此:

SELECT nextval('customers')
将被以下内容取代:

SELECT get_new_rand_id('customer')
然后,该函数将返回一个数值,例如:
[1-9][0-9]{9}
,其中最后一个数字是校验和

我关注的是:

  • 我如何使它原子化
  • 如何避免两次返回相同的id(尝试将其插入到具有唯一约束的列中会发现这一点,但我认为这太晚了)
  • 这是个好主意吗
  • 注1:我不想使用uuid,因为它要与客户进行通信,而10位数的uuid要比36个字符的uuid简单得多

    注意2:该函数很少使用
    选择get\u new\u rand\u id()
    调用,而是在id列上指定为默认值,而不是
    nextval()

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

  • 那我为什么要这样把事情复杂化呢?目的是向客户隐藏主键

    我给每个新客户一个独特的 customerId(在中生成的序列号) (db)。既然我这么说了 客户的电话号码是 对我的竞争对手来说,这是一项相当简单的任务 监控我的业务(有 其他编号,如发票编号和 订购具有相同 属性)。正是这个监控我 我想做一点 更难(注:并非不可能,但 更难)

  • 为什么是支票数字

    在谈到隐藏序列号之前,我在ordernr中添加了一个校验位,因为在生产过程中的某些点上会出现笨手笨脚的手指,我认为这将是一个很好的实践

  • 在阅读了讨论之后,我可以肯定地看到,我的方法并不是解决问题的最佳方法,但我对如何解决这个问题没有其他好的想法,所以请在这里帮助我

  • 我是否应该添加一个额外的列,将我公开给客户的id放在其中,并将序列号作为主键
  • 我如何才能生成以一种合理有效的方式公开的id
  • 是否需要校验位

  • 你最好的选择可能是某种形式的散列函数,然后在末尾添加一个校验和。

    我在你的问题上添加了我的评论,然后意识到我应该更好地解释自己。。。我道歉

    用户可以看到第二个键,而不是主键。该密钥可以使用主密钥作为您描述的哈希函数的种子,并且是用于查找的密钥。该键将由插入后的触发器生成(这比试图确保操作的原子性要简单得多),并且

    这是你与客户分享的关键,而不是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是一个有用的问题-但是您需要