TL; ดร
นี่คือเวอร์ชันที่คุณไม่จำเป็นต้องใช้มนุษย์ในการอ่านค่าและพิมพ์ออกมาเอง
CREATE SEQUENCE foo_a_seq OWNED BY foo.a;
SELECT setval('foo_a_seq', coalesce(max(a), 0) + 1, false) FROM foo;
ALTER TABLE foo ALTER COLUMN a SET DEFAULT nextval('foo_a_seq');
อีกทางเลือกหนึ่งคือใช้การFunction
แชร์ที่ใช้ซ้ำได้ในตอนท้ายของคำตอบนี้
โซลูชันที่ไม่โต้ตอบ
เพียงเพิ่มคำตอบอีกสองคำตอบสำหรับพวกเราที่จำเป็นต้องSequence
สร้างสิ่งเหล่านี้โดยสคริปต์ที่ไม่โต้ตอบในขณะที่แพตช์ฐานข้อมูลแบบสด
นั่นคือเมื่อคุณไม่ต้องการSELECT
ค่าด้วยตนเองและพิมพ์ด้วยตัวคุณเองในCREATE
คำสั่งที่ตามมา
ในระยะสั้นคุณไม่สามารถทำได้:
CREATE SEQUENCE foo_a_seq
START WITH ( SELECT max(a) + 1 FROM foo );
... เนื่องจากSTART [WITH]
อนุประโยคCREATE SEQUENCE
คาดว่าค่าไม่ใช่แบบสอบถามย่อย
หมายเหตุ: ตามกฎของหัวแม่มือที่นำไปใช้กับทุกคนที่ไม่ใช่ CRUD ( เช่น : อื่นใดนอกเหนือจากINSERT
, SELECT
, UPDATE
, DELETE
) งบในpgSQL AFAIK
อย่างไรก็ตามsetval()
ไม่! ดังนั้นสิ่งต่อไปนี้ทำได้ดีมาก:
SELECT setval('foo_a_seq', max(a)) FROM foo;
หากไม่มีข้อมูลและคุณไม่ (ต้องการ) ทราบให้ใช้coalesce()
เพื่อตั้งค่าเริ่มต้น:
SELECT setval('foo_a_seq', coalesce(max(a), 0)) FROM foo;
อย่างไรก็ตามการตั้งค่าลำดับปัจจุบัน0
เป็นเงอะงะหากไม่ผิดกฎหมาย
การใช้รูปแบบพารามิเตอร์สามตัวsetval
จะเหมาะสมกว่า:
SELECT setval('foo_a_seq', coalesce(max(a), 0) + 1, false) FROM foo;
การตั้งค่าพารามิเตอร์ที่สามที่เป็นทางเลือกของsetval
to false
จะป้องกันไม่ให้ตัวเลือกถัดไปnextval
เลื่อนลำดับก่อนที่จะส่งคืนค่าดังนั้น:
ถัดไปnextval
จะกลับมาว่าค่าที่ระบุและ Commences nextval
ก้าวหน้าลำดับที่มีดังต่อไปนี้
- จากรายการนี้ในเอกสารประกอบ
ในบันทึกที่ไม่เกี่ยวข้องคุณสามารถระบุคอลัมน์ที่เป็นเจ้าของSequence
ได้โดยตรงโดยCREATE
ไม่ต้องแก้ไขภายหลัง:
CREATE SEQUENCE foo_a_seq OWNED BY foo.a;
สรุป:
CREATE SEQUENCE foo_a_seq OWNED BY foo.a;
SELECT setval('foo_a_seq', coalesce(max(a), 0) + 1, false) FROM foo;
ALTER TABLE foo ALTER COLUMN a SET DEFAULT nextval('foo_a_seq');
การใช้ไฟล์ Function
หรือหากคุณกำลังวางแผนที่จะทำสิ่งนี้สำหรับหลายคอลัมน์คุณสามารถเลือกใช้Function
ไฟล์.
CREATE OR REPLACE FUNCTION make_into_serial(table_name TEXT, column_name TEXT) RETURNS INTEGER AS $$
DECLARE
start_with INTEGER;
sequence_name TEXT;
BEGIN
sequence_name := table_name || '_' || column_name || '_seq';
EXECUTE 'SELECT coalesce(max(' || column_name || '), 0) + 1 FROM ' || table_name
INTO start_with;
EXECUTE 'CREATE SEQUENCE ' || sequence_name ||
' START WITH ' || start_with ||
' OWNED BY ' || table_name || '.' || column_name;
EXECUTE 'ALTER TABLE ' || table_name || ' ALTER COLUMN ' || column_name ||
' SET DEFAULT nextVal(''' || sequence_name || ''')';
RETURN start_with;
END;
$$ LANGUAGE plpgsql VOLATILE;
ใช้มันดังนี้:
INSERT INTO foo (data) VALUES ('asdf');
SELECT make_into_serial('foo', 'a');
INSERT INTO foo (data) VALUES ('asdf');
SERIAL
ขณะนี้ประเภทหลอกเป็นแบบดั้งเดิมแทนที่ด้วยGENERATED … AS IDENTITY
คุณลักษณะใหม่ที่กำหนดในSQL: 2003ใน Postgres 10 และใหม่กว่า ดูคำอธิบาย