ฉันเปลี่ยนจาก MySQL เป็น PostgreSQL และสงสัยว่าฉันจะทำค่าการรวมอัตโนมัติได้อย่างไร ฉันเห็นใน PostgreSQL เอกสารประเภทข้อมูล "อนุกรม" แต่ฉันได้รับข้อผิดพลาดทางไวยากรณ์เมื่อใช้มัน (ใน v8.0)
ฉันเปลี่ยนจาก MySQL เป็น PostgreSQL และสงสัยว่าฉันจะทำค่าการรวมอัตโนมัติได้อย่างไร ฉันเห็นใน PostgreSQL เอกสารประเภทข้อมูล "อนุกรม" แต่ฉันได้รับข้อผิดพลาดทางไวยากรณ์เมื่อใช้มัน (ใน v8.0)
คำตอบ:
ใช่แล้ว SERIAL เป็นฟังก์ชั่นที่เทียบเท่า
CREATE TABLE foo (
id SERIAL,
bar varchar);
INSERT INTO foo (bar) values ('blah');
INSERT INTO foo (bar) values ('blah');
SELECT * FROM foo;
1,blah
2,blah
SERIAL เป็นเพียงสร้างตารางเวลาแมโครรอบลำดับ คุณไม่สามารถแก้ไข SERIAL ลงในคอลัมน์ที่มีอยู่
"Table"
และ"table"
แล้วก็ปล่อยให้มัน unquoted และ canonicalize table
มัน การประชุมไม่เคยใช้เครื่องหมายคำพูดใน Pg คุณสามารถใช้ชื่อกรณีแบบผสมเพื่อการปรากฏถ้าคุณต้องการคุณไม่จำเป็นต้องใช้: CREATE TABLE fooBar ( .. ); SELECT * FROM fooBar;
จะทำงานตามที่SELECT * FROM foobar
ต้องการ
คุณสามารถใช้อื่น ๆชนิดข้อมูลจำนวนเต็มsmallint
เช่น
ตัวอย่าง:
CREATE SEQUENCE user_id_seq;
CREATE TABLE user (
user_id smallint NOT NULL DEFAULT nextval('user_id_seq')
);
ALTER SEQUENCE user_id_seq OWNED BY user.user_id;
ดีกว่าที่จะใช้ชนิดข้อมูลของคุณเองมากกว่าผู้ใช้ชนิดข้อมูลแบบอนุกรม
CREATE SEQUENCE
postgresql.org/docs/8.1/interactive/sql-createsequence.html ) . อย่างไรก็ตามฉันไม่แน่ใจว่าทำไมคุณเปลี่ยนเจ้าของ
หากคุณต้องการเพิ่มลำดับลงใน id ซึ่งมีอยู่แล้วคุณสามารถใช้:
CREATE SEQUENCE user_id_seq;
ALTER TABLE user ALTER user_id SET DEFAULT NEXTVAL('user_id_seq');
ALTER COLUMN user_id
เหรอ?
ERROR: syntax error at or near "DEFAULT"
คำแนะนำใด ๆ
ในขณะที่ดูเหมือนว่าลำดับจะเทียบเท่ากับ MySQL auto_increment แต่ก็มีความแตกต่างเล็กน้อย แต่สำคัญ:
คอลัมน์อนุกรมได้รับการเพิ่มขึ้นจากการสืบค้นที่ล้มเหลว สิ่งนี้นำไปสู่การกระจายตัวของแบบสอบถามที่ล้มเหลวไม่ใช่แค่การลบแถว ตัวอย่างเช่นรันเคียวรีต่อไปนี้บนฐานข้อมูล PostgreSQL ของคุณ:
CREATE TABLE table1 (
uid serial NOT NULL PRIMARY KEY,
col_b integer NOT NULL,
CHECK (col_b>=0)
);
INSERT INTO table1 (col_b) VALUES(1);
INSERT INTO table1 (col_b) VALUES(-1);
INSERT INTO table1 (col_b) VALUES(2);
SELECT * FROM table1;
คุณควรได้รับผลลัพธ์ต่อไปนี้:
uid | col_b
-----+-------
1 | 1
3 | 2
(2 rows)
สังเกตว่า uid ไปจาก 1 ถึง 3 แทนที่จะเป็น 1 ถึง 2 ได้อย่างไร
สิ่งนี้ยังคงเกิดขึ้นหากคุณต้องสร้างลำดับของคุณเองด้วย:
CREATE SEQUENCE table1_seq;
CREATE TABLE table1 (
col_a smallint NOT NULL DEFAULT nextval('table1_seq'),
col_b integer NOT NULL,
CHECK (col_b>=0)
);
ALTER SEQUENCE table1_seq OWNED BY table1.col_a;
หากคุณต้องการทดสอบว่า MySQL แตกต่างกันอย่างไรให้รันสิ่งต่อไปนี้บนฐานข้อมูล MySQL:
CREATE TABLE table1 (
uid int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
col_b int unsigned NOT NULL
);
INSERT INTO table1 (col_b) VALUES(1);
INSERT INTO table1 (col_b) VALUES(-1);
INSERT INTO table1 (col_b) VALUES(2);
คุณควรได้รับสิ่งต่อไปนี้โดยไม่มีการจัดการ :
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
+-----+-------+
2 rows in set (0.00 sec)
สิ่งนี้ชี้ให้เห็นโดย @trev ในคำตอบก่อนหน้า
เพื่อจำลองสิ่งนี้ตั้ง uid เป็น 4 ซึ่งจะ "ปะทะกัน" ในภายหลัง
INSERT INTO table1 (uid, col_b) VALUES(5, 5);
ข้อมูลตาราง:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
(3 rows)
เรียกใช้ตัวแทรกอื่น:
INSERT INTO table1 (col_b) VALUES(6);
ข้อมูลตาราง:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
4 | 6
ตอนนี้ถ้าคุณเรียกใช้ตัวแทรกอื่น:
INSERT INTO table1 (col_b) VALUES(7);
มันจะล้มเหลวด้วยข้อความแสดงข้อผิดพลาดต่อไปนี้:
ข้อผิดพลาด: ค่าคีย์ที่ซ้ำกันละเมิดข้อ จำกัด ที่ไม่ซ้ำกัน "table1_pkey" รายละเอียด: Key (uid) = (5) มีอยู่แล้ว
ในทางตรงกันข้าม MySQL จะจัดการสิ่งนี้อย่างสง่างามดังที่แสดงด้านล่าง:
INSERT INTO table1 (uid, col_b) VALUES(4, 4);
ตอนนี้แทรกแถวอื่นโดยไม่มีการตั้งค่า uid
INSERT INTO table1 (col_b) VALUES(3);
การสืบค้นไม่ได้ล้มเหลว uid เพียงข้ามไปที่ 5:
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
| 4 | 4 |
| 5 | 3 |
+-----+-------+
ทำการทดสอบบน MySQL 5.6.33 สำหรับ Linux (x86_64) และ PostgreSQL 9.4.9
เริ่มต้นด้วย Postgres 10 สนับสนุนคอลัมน์ข้อมูลประจำตัวตามที่กำหนดโดยมาตรฐาน SQL:
create table foo
(
id integer generated always as identity
);
สร้างคอลัมน์ข้อมูลประจำตัวที่ไม่สามารถเขียนทับได้เว้นแต่จะมีการขออย่างชัดเจน การแทรกต่อไปนี้จะล้มเหลวโดยมีคอลัมน์ที่กำหนดเป็นgenerated always
:
insert into foo (id)
values (1);
อย่างไรก็ตามสิ่งนี้สามารถแก้ไขได้:
insert into foo (id) overriding system value
values (1);
เมื่อใช้ตัวเลือกgenerated by default
นี่เป็นพฤติกรรมเดียวกับserial
การใช้งานที่มีอยู่:
create table foo
(
id integer generated by default as identity
);
เมื่อมีการให้ค่าด้วยตนเองลำดับที่จำเป็นต้องปรับด้วยตนเองเช่นเดียวกับserial
คอลัมน์
คอลัมน์ข้อมูลประจำตัวไม่ใช่คีย์หลักโดยค่าเริ่มต้น (เช่นเดียวกับserial
คอลัมน์) หากควรเป็นหนึ่งข้อ จำกัด คีย์หลักจะต้องกำหนดด้วยตนเอง
ขออภัยที่จะถามคำถามเก่า แต่นี่เป็นคำถาม / คำตอบสแต็คล้นแรกที่โผล่ขึ้นมาบน Google
โพสต์นี้ (ซึ่งขึ้นมาเป็นลำดับแรกบน Google) พูดถึงการใช้ไวยากรณ์ที่อัปเดตมากขึ้นสำหรับ PostgreSQL 10: https://blog.2ndquadrant.com/postgresql-10-identity-columns/
ซึ่งเกิดขึ้นเป็น:
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
);
หวังว่าจะช่วย :)
GENERATED … AS IDENTITY
คำสั่งคือ SQL มาตรฐาน เพิ่มครั้งแรกในSQL: 2003 ที่แล้วชี้แจงในSQL: 2008 ดูคุณสมบัติ # T174 & F386 & T178
คุณต้องระวังไม่ให้แทรกลงใน SERIAL หรือฟิลด์ลำดับโดยตรงมิฉะนั้นการเขียนของคุณจะล้มเหลวเมื่อลำดับมาถึงค่าที่แทรกไว้:
-- Table: "test"
-- DROP TABLE test;
CREATE TABLE test
(
"ID" SERIAL,
"Rank" integer NOT NULL,
"GermanHeadword" "text" [] NOT NULL,
"PartOfSpeech" "text" NOT NULL,
"ExampleSentence" "text" NOT NULL,
"EnglishGloss" "text"[] NOT NULL,
CONSTRAINT "PKey" PRIMARY KEY ("ID", "Rank")
)
WITH (
OIDS=FALSE
);
-- ALTER TABLE test OWNER TO postgres;
INSERT INTO test("Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss")
VALUES (1, '{"der", "die", "das", "den", "dem", "des"}', 'art', 'Der Mann küsst die Frau und das Kind schaut zu', '{"the", "of the" }');
INSERT INTO test("ID", "Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss")
VALUES (2, 1, '{"der", "die", "das"}', 'pron', 'Das ist mein Fahrrad', '{"that", "those"}');
INSERT INTO test("Rank", "GermanHeadword", "PartOfSpeech", "ExampleSentence", "EnglishGloss")
VALUES (1, '{"der", "die", "das"}', 'pron', 'Die Frau, die nebenen wohnt, heißt Renate', '{"that", "who"}');
SELECT * from test;
ในบริบทของคำถามที่ถามและในการตอบกลับความคิดเห็นโดย @ sereja1c การSERIAL
สร้างจะสร้างลำดับโดยปริยายดังนั้นสำหรับตัวอย่างด้านบน -
CREATE TABLE foo (id SERIAL,bar varchar);
CREATE TABLE
โดยปริยายจะสร้างลำดับสำหรับคอลัมน์อนุกรมfoo_id_seq
foo.id
ดังนั้นSERIAL
[4 Bytes] นั้นดีสำหรับการใช้งานที่ง่ายเว้นแต่คุณต้องการประเภทข้อมูลเฉพาะสำหรับ id ของคุณ
วิธีนี้จะทำงานได้อย่างแน่นอนฉันหวังว่ามันจะช่วย:
CREATE TABLE fruits(
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL
);
INSERT INTO fruits(id,name) VALUES(DEFAULT,'apple');
or
INSERT INTO fruits VALUES(DEFAULT,'apple');
คุณสามารถตรวจสอบรายละเอียดนี้ได้ในลิงค์ถัดไป: http://www.postgresqltutorial.com/postgresql-serial/
ตั้งแต่ PostgreSQL 10
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
payload text
);