แรงบันดาลใจจากคำตอบอื่น ๆ ที่นี่ฉันสร้างฟังก์ชัน SQL เพื่อทำการโยกย้ายลำดับ ฟังก์ชันจะย้ายลำดับคีย์หลักไปยังลำดับที่ต่อเนื่องกันใหม่โดยเริ่มต้นด้วยค่าใด ๆ (> = 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)