次のような英数字シーケンスを作成します。
AAAA0000
AAAA0001
AAAA0002
AAAA0003
.
.
.
AAAA9999
AAAB0000
AAAB0001
.
.
.
ZZZZ9999
これを行うためにこのストアプロシージャを作成しましたが、速度が遅すぎます。
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の有無にかかわらずそれを行う別の方法はありますか?
これは、いくつかの単純なシリーズを生成する2つの共通テーブル式(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
_
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
_