How to generate a random, unique, alphanumeric ID of length N in Postgres 9.6+?

后端 未结 6 604
走了就别回头了
走了就别回头了 2020-12-25 14:59

I\'ve seen a bunch of different solutions on StackOverflow that span many years and many Postgres versions, but with some of the newer features like gen_random_bytes I want

6条回答
  •  心在旅途
    2020-12-25 15:41

    Review,

    1. 26 characters in [a-z]
    2. 26 characters in [A-Z]
    3. 10 characters in [0-9]
    4. 62 characters in [a-zA-Z0-9] (base62)
    5. The function substring(string [from int] [for int]) looks useful.

    So it looks something like this. First we demonstrate that we can take the random-range and pull from it.

    SELECT substring(
      'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
      1, -- 1 is 'a', 62 is '9'
      1,
    );
    

    Now we need a range between 1 and 63

    SELECT trunc(random()*62+1)::int+1
    FROM generate_series(1,1e2) AS gs(x)
    

    This gets us there.. Now we just have to join the two..

    SELECT substring(
      'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
      trunc(random()*62)::int+1
      1
    )
    FROM generate_series(1,1e2) AS gs(x);
    

    Then we wrap it in an ARRAY constructor (because this is fast)

    SELECT ARRAY(
      SELECT substring(
        'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
        trunc(random()*62)::int+1,
        1
      )
      FROM generate_series(1,1e2) AS gs(x)
    );
    

    And, we call array_to_string() to get a text.

    SELECT array_to_string(
      ARRAY(
          SELECT substring(
            'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
            trunc(random()*62)::int+1,
            1
          )
          FROM generate_series(1,1e2) AS gs(x)
      )
      , ''
    );
    

    From here we can even turn it into a function..

    CREATE FUNCTION random_string(randomLength int)
    RETURNS text AS $$
    SELECT array_to_string(
      ARRAY(
          SELECT substring(
            'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
            trunc(random()*62)::int+1,
            1
          )
          FROM generate_series(1,randomLength) AS gs(x)
      )
      , ''
    )
    $$ LANGUAGE SQL
    RETURNS NULL ON NULL INPUT
    VOLATILE LEAKPROOF;
    

    and then

    SELECT * FROM random_string(10);
    

提交回复
热议问题