Ich wechsle von MySQL zu PostgreSQL und habe mich gefragt, wie ich Werte automatisch erhöhen kann. Ich habe in den PostgreSQL-Dokumenten einen Datentyp "serial" gesehen, aber bei der Verwendung (in Version 8.0) treten Syntaxfehler auf.
Ich wechsle von MySQL zu PostgreSQL und habe mich gefragt, wie ich Werte automatisch erhöhen kann. Ich habe in den PostgreSQL-Dokumenten einen Datentyp "serial" gesehen, aber bei der Verwendung (in Version 8.0) treten Syntaxfehler auf.
Antworten:
Ja, SERIAL ist die entsprechende Funktion.
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 ist nur ein Makro zum Erstellen einer Tabellenzeit um Sequenzen. Sie können SERIAL nicht in eine vorhandene Spalte ändern.
"Table"
und "table"
lassen sie dann einfach nicht zitiert und kanonisieren sie table
. Die Konvention ist einfach, niemals Anführungszeichen in Seite zu verwenden. Sie können, wenn Sie möchten, gemischte Fallnamen für das Erscheinungsbild verwenden, benötigen sie jedoch nicht: Funktioniert CREATE TABLE fooBar ( .. ); SELECT * FROM fooBar;
wie auch SELECT * FROM foobar
.
Sie können jeden anderen ganzzahligen Datentyp verwenden , z smallint
.
Beispiel:
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;
Verwenden Sie lieber Ihren eigenen Datentyp als den seriellen Datentyp des Benutzers .
CREATE SEQUENCE
festlegte (nach dem Lesen von postgresql.org/docs/8.1/interactive/sql-createsequence.html ). . Ich bin mir jedoch nicht ganz sicher, warum Sie den Besitzer gewechselt haben.
Wenn Sie der bereits vorhandenen Tabelle eine Sequenz zur ID hinzufügen möchten, können Sie Folgendes verwenden:
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"
Irgendwelche Vorschläge?
Während es sieht aus wie Sequenzen das sind äquivalent zu MySQL auto_increment, gibt es einige feine , aber wichtige Unterschiede:
Die serielle Spalte wird bei fehlgeschlagenen Abfragen erhöht. Dies führt zu einer Fragmentierung von fehlgeschlagenen Abfragen, nicht nur zum Löschen von Zeilen. Führen Sie beispielsweise die folgenden Abfragen in Ihrer PostgreSQL-Datenbank aus:
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;
Sie sollten die folgende Ausgabe erhalten:
uid | col_b
-----+-------
1 | 1
3 | 2
(2 rows)
Beachten Sie, wie die UID von 1 auf 3 anstatt von 1 auf 2 wechselt.
Dies tritt immer noch auf, wenn Sie Ihre eigene Sequenz manuell erstellen mit:
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;
Wenn Sie testen möchten, wie sich MySQL unterscheidet, führen Sie Folgendes in einer MySQL-Datenbank aus:
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);
Sie sollten ohne Fraging Folgendes erhalten :
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
+-----+-------+
2 rows in set (0.00 sec)
Dies wurde von @trev in einer früheren Antwort hervorgehoben.
Um dies manuell zu simulieren, setzen Sie die UID auf 4, was später "zusammenstößt".
INSERT INTO table1 (uid, col_b) VALUES(5, 5);
Tabellendaten:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
(3 rows)
Führen Sie eine weitere Einfügung aus:
INSERT INTO table1 (col_b) VALUES(6);
Tabellendaten:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
4 | 6
Wenn Sie nun eine andere Einfügung ausführen:
INSERT INTO table1 (col_b) VALUES(7);
Es wird mit der folgenden Fehlermeldung fehlschlagen:
FEHLER: Doppelter Schlüsselwert verletzt eindeutige Einschränkung "table1_pkey" DETAIL: Schlüssel (uid) = (5) existiert bereits.
Im Gegensatz dazu wird MySQL dies wie unten gezeigt ordnungsgemäß handhaben:
INSERT INTO table1 (uid, col_b) VALUES(4, 4);
Fügen Sie nun eine weitere Zeile ein, ohne uid einzustellen
INSERT INTO table1 (col_b) VALUES(3);
Die Abfrage schlägt nicht fehl, uid springt einfach zu 5:
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
| 4 | 4 |
| 5 | 3 |
+-----+-------+
Die Tests wurden unter MySQL 5.6.33 für Linux (x86_64) und PostgreSQL 9.4.9 durchgeführt
Ab Postgres 10 werden auch Identitätsspalten gemäß dem SQL-Standard unterstützt:
create table foo
(
id integer generated always as identity
);
Erstellt eine Identitätsspalte, die nur überschrieben werden kann, wenn dies ausdrücklich angefordert wird. Das folgende Einfügen schlägt mit einer Spalte fehl, die wie folgt definiert ist generated always
:
insert into foo (id)
values (1);
Dies kann jedoch außer Kraft gesetzt werden:
insert into foo (id) overriding system value
values (1);
Bei Verwendung der Option entspricht generated by default
dies im Wesentlichen dem Verhalten der vorhandenen serial
Implementierung:
create table foo
(
id integer generated by default as identity
);
Wenn ein Wert manuell angegeben wird, muss die zugrunde liegende Sequenz ebenfalls manuell angepasst werden - genau wie bei einer serial
Spalte.
Eine Identitätsspalte ist standardmäßig kein Primärschlüssel (genau wie eine serial
Spalte). Sollte dies der Fall sein, muss eine Primärschlüsseleinschränkung manuell definiert werden.
Es tut uns leid, eine alte Frage erneut aufzubereiten, aber dies war die erste Frage / Antwort zum Stapelüberlauf, die bei Google aufgetaucht ist.
In diesem Beitrag (der zuerst bei Google veröffentlicht wurde) wird die Verwendung der aktualisierten Syntax für PostgreSQL 10 beschrieben: https://blog.2ndquadrant.com/postgresql-10-identity-columns/
was zufällig ist:
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
);
Ich hoffe, das hilft :)
GENERATED … AS IDENTITY
Befehle Standard-SQL. Zuerst in SQL: 2003 hinzugefügt , dann in SQL: 2008 geklärt . Siehe Funktionen # T174 & F386 & T178.
Sie müssen darauf achten, nicht direkt in Ihr SERIAL- oder Sequenzfeld einzufügen, da sonst das Schreiben fehlschlägt, wenn die Sequenz den eingefügten Wert erreicht:
-- 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;
Im Kontext der gestellten Frage und als Antwort auf den Kommentar von @ sereja1c werden beim SERIAL
impliziten Erstellen Sequenzen erstellt.
CREATE TABLE foo (id SERIAL,bar varchar);
CREATE TABLE
würde implizit eine Sequenz foo_id_seq
für die serielle Spalte erstellen foo.id
. Daher ist SERIAL
[4 Bytes] für die Benutzerfreundlichkeit gut, es sei denn, Sie benötigen einen bestimmten Datentyp für Ihre ID.
Dieser Weg wird sicher funktionieren, ich hoffe es hilft:
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');
Sie können dies anhand der Details im nächsten Link überprüfen: http://www.postgresqltutorial.com/postgresql-serial/
Seit PostgreSQL 10
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
payload text
);