Saya beralih dari MySQL ke PostgreSQL dan bertanya-tanya bagaimana saya bisa melakukan nilai autoincrement. Saya melihat di PostgreSQL mendokumentasikan datatype "serial", tapi saya mendapatkan kesalahan sintaks saat menggunakannya (dalam v8.0).
Saya beralih dari MySQL ke PostgreSQL dan bertanya-tanya bagaimana saya bisa melakukan nilai autoincrement. Saya melihat di PostgreSQL mendokumentasikan datatype "serial", tapi saya mendapatkan kesalahan sintaks saat menggunakannya (dalam v8.0).
Jawaban:
Ya, SERIAL adalah fungsi yang setara.
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 hanyalah makro waktu pembuatan tabel di sekitar sekuens. Anda tidak dapat mengubah SERIAL ke kolom yang ada.
"Table"
dan "table"
kemudian hanya meninggalkannya kuotasi dan canonicalize ke table
. Konvensi ini tidak pernah menggunakan kutipan dalam hal. Anda dapat, jika ingin, menggunakan nama case campuran untuk penampilan, hanya saja tidak memerlukannya: CREATE TABLE fooBar ( .. ); SELECT * FROM fooBar;
akan berfungsi, seperti yang akan terjadi SELECT * FROM foobar
.
Anda dapat menggunakan tipe data integer lainnya , seperti smallint
.
Contoh:
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;
Lebih baik menggunakan tipe data Anda sendiri, daripada tipe data serial pengguna .
CREATE SEQUENCE
postgresql.org/docs/8.1/interactive/sql-createsequence.html ) . NAMUN, saya tidak yakin mengapa Anda mengubah pemiliknya.
Jika Anda ingin menambahkan urutan ke id di tabel yang sudah ada, Anda dapat menggunakan:
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"
Ada saran?
Walaupun sepertinya urutannya setara dengan MySQL auto_increment, ada beberapa perbedaan yang halus tetapi penting:
Kolom serial akan bertambah pada kueri yang gagal. Ini mengarah ke fragmentasi dari kueri yang gagal, bukan hanya penghapusan baris. Sebagai contoh, jalankan query berikut pada database PostgreSQL Anda:
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;
Anda harus mendapatkan output berikut:
uid | col_b
-----+-------
1 | 1
3 | 2
(2 rows)
Perhatikan bagaimana Anda beralih dari 1 ke 3 bukannya 1 ke 2.
Ini masih terjadi jika Anda secara manual membuat urutan Anda sendiri dengan:
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;
Jika Anda ingin menguji perbedaan MySQL, jalankan yang berikut di database 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);
Anda harus mendapatkan yang berikut tanpa frmentasi :
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
+-----+-------+
2 rows in set (0.00 sec)
Ini ditunjukkan oleh @trev dalam jawaban sebelumnya.
Untuk mensimulasikan ini secara manual atur uid ke 4 yang akan "clash" nanti.
INSERT INTO table1 (uid, col_b) VALUES(5, 5);
Data tabel:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
(3 rows)
Jalankan sisipan lain:
INSERT INTO table1 (col_b) VALUES(6);
Data tabel:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
4 | 6
Sekarang jika Anda menjalankan sisipan lain:
INSERT INTO table1 (col_b) VALUES(7);
Ini akan gagal dengan pesan kesalahan berikut:
GALAT: nilai kunci duplikat melanggar batasan unik "table1_pkey" DETAIL: Kunci (uid) = (5) sudah ada.
Sebaliknya, MySQL akan menangani ini dengan anggun seperti yang ditunjukkan di bawah ini:
INSERT INTO table1 (uid, col_b) VALUES(4, 4);
Sekarang masukkan baris lain tanpa pengaturan uid
INSERT INTO table1 (col_b) VALUES(3);
Permintaan tidak gagal, Anda hanya perlu melompat ke 5:
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
| 4 | 4 |
| 5 | 3 |
+-----+-------+
Pengujian dilakukan pada MySQL 5.6.33, untuk Linux (x86_64) dan PostgreSQL 9.4.9
Dimulai dengan Postgres 10, kolom identitas seperti yang didefinisikan oleh standar SQL juga didukung:
create table foo
(
id integer generated always as identity
);
membuat kolom identitas yang tidak bisa diganti kecuali diminta secara eksplisit. Sisipan berikut akan gagal dengan kolom yang didefinisikan sebagai generated always
:
insert into foo (id)
values (1);
Namun ini dapat ditolak:
insert into foo (id) overriding system value
values (1);
Saat menggunakan opsi generated by default
ini pada dasarnya perilaku yang sama dengan serial
implementasi yang ada :
create table foo
(
id integer generated by default as identity
);
Ketika nilai diberikan secara manual, urutan yang mendasarinya perlu disesuaikan secara manual juga - sama seperti dengan serial
kolom.
Kolom identitas bukan kunci utama secara default (seperti serial
kolom). Jika harus satu, batasan kunci primer perlu didefinisikan secara manual.
Maaf, untuk mengulangi pertanyaan lama, tapi ini adalah pertanyaan / jawaban Stack Overflow pertama yang muncul di Google.
Posting ini (yang muncul pertama kali di Google) berbicara tentang penggunaan sintaks yang lebih diperbarui untuk PostgreSQL 10: https://blog.2ndquadrant.com/postgresql-10-identity-columns/
yang kebetulan adalah:
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
);
Semoga itu bisa membantu :)
GENERATED … AS IDENTITY
perintahnya adalah SQL standar. Pertama ditambahkan dalam SQL: 2003 , kemudian diklarifikasi dalam SQL: 2008 . Lihat fitur # T174 & F386 & T178.
Anda harus berhati-hati untuk tidak memasukkan langsung ke bidang SERIAL atau urutan Anda, jika tidak, penulisan Anda akan gagal ketika urutan mencapai nilai yang dimasukkan:
-- 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;
Dalam konteks pertanyaan yang diajukan dan sebagai balasan atas komentar oleh @ sereja1c, membuat SERIAL
secara implisit menciptakan urutan, jadi untuk contoh di atas-
CREATE TABLE foo (id SERIAL,bar varchar);
CREATE TABLE
secara implisit akan membuat urutan foo_id_seq
untuk kolom serial foo.id
. Karenanya, SERIAL
[4 Bytes] bagus untuk kemudahan penggunaan kecuali Anda membutuhkan tipe data khusus untuk id Anda.
Cara ini pasti akan berhasil, saya harap ini membantu:
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');
Anda dapat memeriksa detail ini di tautan berikutnya: http://www.postgresqltutorial.com/postgresql-serial/
Sejak PostgreSQL 10
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
payload text
);