Tôi đang chuyển từ MySQL sang PostgreSQL và đang tự hỏi làm thế nào tôi có thể thực hiện các giá trị tự động. Tôi đã thấy trong tài liệu PostgreQuery một kiểu dữ liệu "nối tiếp", nhưng tôi gặp lỗi cú pháp khi sử dụng nó (trong v8.0).
Tôi đang chuyển từ MySQL sang PostgreSQL và đang tự hỏi làm thế nào tôi có thể thực hiện các giá trị tự động. Tôi đã thấy trong tài liệu PostgreQuery một kiểu dữ liệu "nối tiếp", nhưng tôi gặp lỗi cú pháp khi sử dụng nó (trong v8.0).
Câu trả lời:
Có, SERIAL là chức năng tương đương.
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 chỉ là một macro thời gian tạo bảng xung quanh các chuỗi. Bạn không thể thay đổi SERIAL trên một cột hiện có.
"Table"
và "table"
sau đó chỉ để lại nó không được trích dẫn và chuẩn hóa nó table
. Quy ước đơn giản là không bao giờ sử dụng dấu ngoặc kép trong PGS. Nếu bạn muốn, bạn có thể sử dụng tên trường hợp hỗn hợp để xuất hiện, chỉ cần không yêu cầu nó: CREATE TABLE fooBar ( .. ); SELECT * FROM fooBar;
sẽ hoạt động, như ý muốn SELECT * FROM foobar
.
Bạn có thể sử dụng bất kỳ loại dữ liệu số nguyên khác , chẳng hạn như smallint
.
Thí dụ :
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;
Tốt hơn là sử dụng kiểu dữ liệu của riêng bạn, thay vì kiểu dữ liệu nối tiếp của người dùng .
CREATE SEQUENCE
postgresql.org/docs/8.1/interactive/sql-createsequence.html ) . TUY NHIÊN, tôi không chắc tại sao bạn thay đổi chủ sở hữu.
Nếu bạn muốn thêm chuỗi vào id trong bảng đã tồn tại, bạn có thể sử dụng:
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"
Có gợi ý nào không?
Mặc dù có vẻ như các chuỗi tương đương với auto_increment của MySQL, có một số khác biệt tinh tế nhưng quan trọng:
Cột nối tiếp được tăng lên trên các truy vấn không thành công. Điều này dẫn đến sự phân mảnh từ các truy vấn không thành công, không chỉ xóa hàng. Ví dụ: chạy các truy vấn sau trên cơ sở dữ liệu PostgreSQL của bạn:
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;
Bạn sẽ nhận được đầu ra sau:
uid | col_b
-----+-------
1 | 1
3 | 2
(2 rows)
Lưu ý cách uid đi từ 1 đến 3 thay vì 1 đến 2.
Điều này vẫn xảy ra nếu bạn tự tạo trình tự của mình bằng:
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;
Nếu bạn muốn kiểm tra MySQL khác nhau như thế nào, hãy chạy như sau trên cơ sở dữ liệu 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);
Bạn sẽ nhận được những điều sau đây không có phân đoạn :
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
+-----+-------+
2 rows in set (0.00 sec)
Điều này đã được @trev chỉ ra trong câu trả lời trước đó.
Để mô phỏng điều này theo cách thủ công, đặt uid thành 4 sẽ "đụng độ" sau.
INSERT INTO table1 (uid, col_b) VALUES(5, 5);
Bảng dữ liệu:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
(3 rows)
Chạy một chèn khác:
INSERT INTO table1 (col_b) VALUES(6);
Bảng dữ liệu:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
4 | 6
Bây giờ nếu bạn chạy chèn khác:
INSERT INTO table1 (col_b) VALUES(7);
Nó sẽ thất bại với thông báo lỗi sau:
LRI: giá trị khóa trùng lặp vi phạm ràng buộc duy nhất "table1_pkey" CHI TIẾT: Khóa (uid) = (5) đã tồn tại.
Ngược lại, MySQL sẽ xử lý việc này một cách duyên dáng như hình dưới đây:
INSERT INTO table1 (uid, col_b) VALUES(4, 4);
Bây giờ chèn một hàng khác mà không đặt uid
INSERT INTO table1 (col_b) VALUES(3);
Truy vấn không thất bại, uid chỉ nhảy đến 5:
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
| 4 | 4 |
| 5 | 3 |
+-----+-------+
Thử nghiệm đã được thực hiện trên MySQL 5.6.33, cho Linux (x86_64) và PostgreQuery 9.4.9
Bắt đầu với Postgres 10, các cột định danh theo định nghĩa của tiêu chuẩn SQL cũng được hỗ trợ:
create table foo
(
id integer generated always as identity
);
tạo một cột danh tính không thể bị ghi đè trừ khi được yêu cầu rõ ràng. Chèn sau đây sẽ thất bại với một cột được xác định là generated always
:
insert into foo (id)
values (1);
Điều này tuy nhiên có thể được ghi đè:
insert into foo (id) overriding system value
values (1);
Khi sử dụng tùy chọn, generated by default
đây thực chất là hành vi tương tự như serial
triển khai hiện có:
create table foo
(
id integer generated by default as identity
);
Khi một giá trị được cung cấp thủ công, trình tự cơ bản cũng cần được điều chỉnh thủ công - giống như với một serial
cột.
Một cột định danh không phải là khóa chính theo mặc định (giống như một serial
cột). Nếu nó phải là một, một ràng buộc khóa chính cần được xác định bằng tay.
Xin lỗi, để làm lại một câu hỏi cũ, nhưng đây là câu hỏi / câu trả lời Stack Overflow đầu tiên xuất hiện trên Google.
Bài đăng này (xuất hiện đầu tiên trên Google) nói về việc sử dụng cú pháp cập nhật hơn cho PostgreQuery 10: https://blog.2ndquadrant.com/postgresql-10-identity-columns/
xảy ra là:
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
);
Mong rằng sẽ giúp :)
GENERATED … AS IDENTITY
lệnh là SQL chuẩn. Lần đầu tiên được thêm vào SQL: 2003 , sau đó được làm rõ trong SQL: 2008 . Xem các tính năng # T174 & F386 & T178.
Bạn phải cẩn thận không chèn trực tiếp vào trường SERIAL hoặc chuỗi, nếu không việc ghi của bạn sẽ thất bại khi chuỗi đạt đến giá trị được chèn:
-- 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;
Trong ngữ cảnh của câu hỏi được hỏi và trả lời nhận xét của @ sereja1c, việc tạo SERIAL
ngầm tạo ra các chuỗi, vì vậy, ví dụ trên-
CREATE TABLE foo (id SERIAL,bar varchar);
CREATE TABLE
sẽ ngầm tạo chuỗi foo_id_seq
cho cột nối tiếp foo.id
. Do đó, SERIAL
[4 byte] rất tốt cho việc sử dụng trừ khi bạn cần một kiểu dữ liệu cụ thể cho id của mình.
Cách này sẽ hoạt động chắc chắn, tôi hy vọng nó sẽ giúp:
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');
Bạn có thể kiểm tra chi tiết này trong liên kết tiếp theo: http://www.postgresqltutorial.com/postgresql-serial/
Kể từ PostgreSQL 10
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
payload text
);