【问题标题】:How to generate random unique number in PostgreSQL using function如何使用函数在 PostgreSQL 中生成随机唯一数
【发布时间】:2014-04-07 09:29:52
【问题描述】:

在PostgreSQL中,如何为列生成随机唯一整数, 返回哪个不存在于表格列中?

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    参见pseudo_encrypt 函数,该函数基于Feistel network 技术实现排列。结合 postgres 序列,这保证了结果的唯一性以及人眼的随机性。

    例子:

    CREATE OR REPLACE FUNCTION pseudo_encrypt(VALUE int) returns int AS $$
    DECLARE
    l1 int;
    l2 int;
    r1 int;
    r2 int;
    i int:=0;
    BEGIN
     l1:= (VALUE >> 16) & 65535;
     r1:= VALUE & 65535;
     WHILE i < 3 LOOP
       l2 := r1;
       r2 := l1 # ((((1366 * r1 + 150889) % 714025) / 714025.0) * 32767)::int;
       l1 := l2;
       r1 := r2;
       i := i + 1;
     END LOOP;
     RETURN ((r1 << 16) + l1);
    END;
    $$ LANGUAGE plpgsql strict immutable;
    
    
    create sequence seq maxvalue 2147483647;
    
    create table tablename(
     id int default pseudo_encrypt(nextval('seq')::int),
     [other columns]
    );
    

    可以在以下位置找到具有 64 位输出空间的变体:pseudo_encrypt() function in plpgsql that takes bigint


    编辑:pseudo_encrypt 仅实现一种排列,并且不接受用户提供的密钥。如果您更喜欢自己的排列,具体取决于密钥,您可以考虑skip32(基于 Skipjack 的 32 位分组密码,具有 10 字节宽的密钥)。

    plpgsql 函数(从 Perl/C 移植)在以下位置可用: https://wiki.postgresql.org/wiki/Skip32

    【讨论】:

    • id 列是否应该是 int 而不是 bigint。意思是我知道 seq 不会返回超出 int 范围的任何内容,但是有什么具体的理由让它变成 bigint 而不是 int? create table tablename( id int default pseudo_encrypt(nextval('seq')::int), [other columns] );
    • @AmolKshirsagar:是的,它现在可能是一个整数。最初回答时,pseudo_encrypt 返回了一个 bigint,但此后已对其进行了修改。答案现已相应更新。
    • Daniel Vérité:有没有办法使用一些脚本来测试这种方法。我已经做出了改变。只是想 100% 确定我不会在生产中犯错误,因为那将是一个严重的问题
    • @AmolKshirsagar:你可以用 40 亿个可能的输入或其中的一小部分来调用这个函数并检查属性(我猜是单一性和分散性)。
    • 如果随机性的目标是防止information disclosure,请不要使用此技术。这种技术掩盖但并未消除披露,因为它使用可预测的伪随机数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    相关资源
    最近更新 更多