ここでの他の回答に触発されて、シーケンス移行を実行するSQL関数を作成しました。この関数は、主キーシーケンスを、既存のシーケンス範囲の内側または外側の任意の値(> = 1)で始まる新しい連続したシーケンスに移動します。
ここでは、スキーマが同じで値が異なる2つのデータベースを1つのデータベースに移行するときに、この関数をどのように使用したかを説明します。
最初に、関数(生成されたSQLコマンドを出力して、実際に何が起こっているかが明確になるようにします):
CREATE OR REPLACE FUNCTION migrate_pkey_sequence
( arg_table text
, arg_column text
, arg_sequence text
, arg_next_value bigint -- Must be >= 1
)
RETURNS int AS $$
DECLARE
result int;
curr_value bigint = arg_next_value - 1;
update_column1 text := format
( 'UPDATE %I SET %I = nextval(%L) + %s'
, arg_table
, arg_column
, arg_sequence
, curr_value
);
alter_sequence text := format
( 'ALTER SEQUENCE %I RESTART WITH %s'
, arg_sequence
, arg_next_value
);
update_column2 text := format
( 'UPDATE %I SET %I = DEFAULT'
, arg_table
, arg_column
);
select_max_column text := format
( 'SELECT coalesce(max(%I), %s) + 1 AS nextval FROM %I'
, arg_column
, curr_value
, arg_table
);
BEGIN
-- Print the SQL command before executing it.
RAISE INFO '%', update_column1;
EXECUTE update_column1;
RAISE INFO '%', alter_sequence;
EXECUTE alter_sequence;
RAISE INFO '%', update_column2;
EXECUTE update_column2;
EXECUTE select_max_column INTO result;
RETURN result;
END $$ LANGUAGE plpgsql;
この関数migrate_pkey_sequence
は次の引数を取ります。
arg_table
:テーブル名(例'example'
)
arg_column
:主キー列名(例 'id'
)
arg_sequence
:シーケンス名(例'example_id_seq'
)
arg_next_value
:移行後の列の次の値
次の操作を実行します。
- 主キー値を自由範囲に移動します。私はそれが
nextval('example_id_seq')
次のようでmax(id)
あり、シーケンスが1で始まると仮定し
ます。これはarg_next_value > max(id)
。の場合も処理します。
- 主キー値をで始まる連続した範囲に移動し
arg_next_value
ます。キー値の順序は保持されますが、範囲内の穴は保持されません。
- シーケンスに続く次の値を出力します。これは、別のテーブルの列を移行して、このテーブルとマージする場合に役立ちます。
例として、次のように定義されたシーケンスとテーブルを使用します(例:を使用psql
)。
# CREATE SEQUENCE example_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
# CREATE TABLE example
( id bigint NOT NULL DEFAULT nextval('example_id_seq'::regclass)
);
次に、いくつかの値を挿入します(たとえば、3から開始)。
# ALTER SEQUENCE example_id_seq RESTART WITH 3;
# INSERT INTO example VALUES (DEFAULT), (DEFAULT), (DEFAULT);
-- id: 3, 4, 5
最後に、example.id
値を1から開始するように移行します。
# SELECT migrate_pkey_sequence('example', 'id', 'example_id_seq', 1);
INFO: 00000: UPDATE example SET id = nextval('example_id_seq') + 0
INFO: 00000: ALTER SEQUENCE example_id_seq RESTART WITH 1
INFO: 00000: UPDATE example SET id = DEFAULT
migrate_pkey_sequence
-----------------------
4
(1 row)
結果:
# SELECT * FROM example;
id
----
1
2
3
(3 rows)