2017-09-06 53 views
1

我想創建一個字母順序是這樣的:Postgres的 - 如何創建一個像AAAA0000字母數字序列等

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; 

此過程使用一個表來存儲序列:

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?

請幫忙。

+0

只需使用常用的順序。 創建函數獲取其基礎序列'nextval',然後將整數值轉碼爲字母數字。 –

+0

你是什麼意思轉碼?我該怎麼做 – juanpscotto

+0

你得到了原始序列號121431.保留除以1000這個數字並增加左邊部分(「AAAA」),而原始數字大於或等於1000. 在finish concatenate left part(「ABCD」)餘數使用零填充左填充。 –

回答

1

它工作非常慢,數據量很大,因爲它必須在插入每一行之前執行。有沒有另外一種方法可以使用或不使用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 
); 

填充整個表,這裏被簡化僅有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

相關問題