jua*_*tto 5 postgresql perl postgresql-9.4
我想创建一个像这样的字母数字序列:
AAAA0000
AAAA0001
AAAA0002
AAAA0003
.
.
.
AAAA9999
AAAB0000
AAAB0001
.
.
.
ZZZZ9999
Run Code Online (Sandbox Code Playgroud)
我创建了这个存储过程来做到这一点,但它太慢了:
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;
Run Code Online (Sandbox Code Playgroud)
此过程使用表来存储序列:
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);
Run Code Online (Sandbox Code Playgroud)
为了增加序列,我使用 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;
Run Code Online (Sandbox Code Playgroud)
对于大量数据,它的运行速度非常慢,因为它必须在插入每一行之前执行。有没有其他方法可以用或不用 Perl 来做到这一点?
我们可以使用几个生成一些简单序列的公共表表达式(CTE)来做到这一点......
with
letters as
(select chr(i) as letter from generate_series(65,90) i),
digits as
(select lpad(i::text,4,'0') as digit from generate_series(0,9999) i)
select l1.letter || l2.letter || l3.letter || l4.letter || d.digit
from letters l1
cross join letters l2
cross join letters l3
cross join letters l4
cross join digits d
Run Code Online (Sandbox Code Playgroud)
letters
letters
生成一系列从 65 到 90 的数字,这恰好是字母“A”到“Z”的 ascii 代码,所以...chr(i)
函数调用生成我们的角色letters
表示字符集“A”到“Z”digits
digits
生成一系列从 0 到 9999 的数字,因为我们要处理字符......lpad(i::text,4,'0')
允许我们将这一系列数字转换为左/零填充字符串digits
代表一组字符 '0000', '0001', ... '9999'cross joins
并将字母/数字附加在一起这是上述内容的dbfiddle 。
对于 dbfiddle,您可以删除该limit/offset
子句以生成完整的集合,或者调整该limit/offset
子句以查看一系列输出。
例如,limit 20 offset 59990
我们得到:
?column?
--------
AAAF9990
AAAF9991
AAAF9992
AAAF9993
AAAF9994
AAAF9995
AAAF9996
AAAF9997
AAAF9998
AAAF9999
AAAG0000
AAAG0001
AAAG0002
AAAG0003
AAAG0004
AAAG0005
AAAG0006
AAAG0007
AAAG0008
AAAG0009
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8817 次 |
最近记录: |