Postgres - 如何创建字母数字序列,如 AAAA0000 等

Postgres - How to create an alphanumeric sequence like AAAA0000 and so on

我想创建一个这样的字母数字序列:

AAAA0000
AAAA0001
AAAA0002
AAAA0003
.
.
.
AAAA9999
AAAB0000
AAAB0001

等等

我已经创建了这个存储过程来执行此操作,但它太慢了:

CREATE OR REPLACE FUNCTION public.fn_batch_seq()
  RETURNS text
  LANGUAGE plpgsql
AS
$body$
DECLARE
  v_sequence TEXT := '';
  v_next_sequence TEXT := '';
  v_existing_id BIGINT := 0;
BEGIN

  /*
  *  VARCHAR BATCH SEQUENCE FOR SIMCARDS
  */
  SELECT "sequence" FROM batch_sequence WHERE id = 1 INTO v_sequence;
  IF v_sequence = '' THEN
    RAISE NOTICE 'Error - No existe ningun registro en batch_sequence almacenado';
    RETURN -500;
  END IF;
  SELECT perl_increment(v_sequence) INTO v_next_sequence;

  IF v_next_sequence = '' THEN
    RAISE NOTICE 'Error - La siguiente secuencia generada devolvio null o vacio';
    RETURN -500;
  END IF;


  UPDATE batch_sequence SET "sequence" = v_next_sequence WHERE id = 1;
  RETURN v_next_sequence;

  EXCEPTION WHEN OTHERS THEN
  /*
  * Other errors
  */
  RAISE NOTICE 'Error General - Posibles causas: No existe la tabla batch_sequence o no existe ningun registro en la misma';
  RETURN -500;

END;
$body$
  VOLATILE
  COST 100;

这个程序使用一个table来存储序列:

CREATE TABLE batch_sequence
(
   id        serial   NOT NULL,
   sequence  text     DEFAULT 'AAAA0000'::text NOT NULL
);

-- Column id is associated with sequence public.batch_sequence_id_seq

ALTER TABLE batch_sequence
   ADD CONSTRAINT batch_sequence_pk
   PRIMARY KEY (id);

为了增加序列,我使用了一个 perl 过程:

CREATE OR REPLACE FUNCTION public.perl_increment(text)
  RETURNS text
  LANGUAGE plperl
AS
$body$
my ($x) = @_;
    if (not defined $x) {
        return undef;
    }
    ++$x;
$body$
  VOLATILE
  COST 100;

对于大量数据,它工作起来非常慢,因为它必须在插入每一行之前执行。是否有另一种方法可以使用或不使用 Perl?

请帮忙。

It works very slow with large amount of data, because it must be executed before inserting every single row. Is there another way to do that with or without Perl?

第一个选项:

创建序列并解码:

CREATE SEQUENCE my_serial START 11110000;

翻译成左边的字母:

select nextval(''my_serial'') INTO v_nextSeq ;
select translate(
       left( trim(to_char(v_nextSeq,'9999')), 4),
       '12345','ABCDE')
       ||
       right( trim(to_char(v_nextSeq,'9999')), 4);

第二个选项:

您可以保留所有序列号然后使用它:

**将 used 字段添加到您的架构中,记得在序列上创建索引 **:

CREATE TABLE batch_sequence
(
   id        serial   NOT NULL,
   sequence  text     DEFAULT 'AAA'::text NOT NULL,
   used      boolean  default false
);

全部填充table,这里简化了2位:

with s as (
  SELECT A.a || B.b  as sequence
  FROM unnest(string_to_array('A B C',' ')) A
  CROSS JOIN unnest(string_to_array('0 1 2 3 4 5 6 7 8 9',' ')) B
) 
insert into batch_sequence ( sequence )
select s.sequence
from s;

Check all is done:

select * from batch_sequence

Results:

| id | sequence |  used |
|----|----------|-------|
| 28 |       A0 | false |
| 29 |       A1 | false |
| 30 |       A2 | false |
| 31 |       A3 | false |
| 32 |       A4 | false |
| 33 |       A5 | false |
| 34 |       A6 | false |
| 35 |       A7 | false |
| 36 |       A8 | false |
| 37 |       A9 | false |
| 38 |       B0 | false |
| 39 |       B1 | false |
| 40 |       B2 | false |
| 41 |       B3 | false |
| 42 |       B4 | false |
| 43 |       B5 | false |
| 44 |       B6 | false |
| 45 |       B7 | false |
| 46 |       B8 | false |
| 47 |       B9 | false |
| 48 |       C0 | false |
| 49 |       C1 | false |
| 50 |       C2 | false |
| 51 |       C3 | false |
| 52 |       C4 | false |
| 53 |       C5 | false |
| 54 |       C6 | false |
| 55 |       C7 | false |
| 56 |       C8 | false |
| 57 |       C9 | false |

创建一个函数来获取新的序列号并将其设置为used