Sto passando da MySQL a PostgreSQL e mi chiedevo come posso fare i valori di autoincremento. Ho visto nei documenti PostgreSQL un tipo di dati "seriale", ma ottengo errori di sintassi quando lo uso (in v8.0).
Sto passando da MySQL a PostgreSQL e mi chiedevo come posso fare i valori di autoincremento. Ho visto nei documenti PostgreSQL un tipo di dati "seriale", ma ottengo errori di sintassi quando lo uso (in v8.0).
Risposte:
Sì, SERIAL è la funzione equivalente.
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 è solo una macro di creazione tabella attorno alle sequenze. Non è possibile modificare SERIAL su una colonna esistente.
"Table"
e "table"
poi lo lasci non quotato e lo canonicalizzi a table
. La convenzione semplicemente non usa mai le virgolette in Pg. Se vuoi, puoi usare nomi di casi misti per l'aspetto, ma non richiederlo: CREATE TABLE fooBar ( .. ); SELECT * FROM fooBar;
funzionerà, come funzionerà SELECT * FROM foobar
.
È possibile utilizzare qualsiasi altro tipo di dati intero , ad esempio smallint
.
Esempio :
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;
Meglio usare il proprio tipo di dati, piuttosto che il tipo di dati seriale dell'utente .
CREATE SEQUENCE
postgresql.org/docs/8.1/interactive/sql-createsequence.html ) . TUTTAVIA, non sono del tutto sicuro del perché tu abbia cambiato proprietario.
Se vuoi aggiungere una sequenza all'id nella tabella che già esiste puoi usare:
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"
qualche suggerimento?
Mentre sembra che le sequenze siano l' equivalente di Auto_increment di MySQL, ci sono alcune differenze sottili ma importanti:
La colonna seriale viene incrementata in caso di query non riuscite. Ciò porta alla frammentazione da query non riuscite, non solo alle eliminazioni di riga. Ad esempio, esegui le seguenti query sul tuo database 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;
Dovresti ottenere il seguente output:
uid | col_b
-----+-------
1 | 1
3 | 2
(2 rows)
Nota come si passa da 1 a 3 anziché da 1 a 2.
Ciò si verifica ancora se si dovesse creare manualmente la propria sequenza con:
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;
Se si desidera verificare la differenza tra MySQL, eseguire quanto segue su un 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);
Si dovrebbe ottenere quanto segue senza frustrazione :
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
+-----+-------+
2 rows in set (0.00 sec)
Questo è stato sottolineato da @trev in una risposta precedente.
Per simularlo, imposta l'UID su 4 che "si scontrerà" in seguito.
INSERT INTO table1 (uid, col_b) VALUES(5, 5);
Dati della tabella:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
(3 rows)
Esegui un altro inserto:
INSERT INTO table1 (col_b) VALUES(6);
Dati della tabella:
uid | col_b
-----+-------
1 | 1
3 | 2
5 | 5
4 | 6
Ora se esegui un altro inserto:
INSERT INTO table1 (col_b) VALUES(7);
Non funzionerà con il seguente messaggio di errore:
ERRORE: il valore chiave duplicato viola il vincolo univoco "table1_pkey" DETTAGLIO: Key (uid) = (5) esiste già.
Al contrario, MySQL gestirà questo con garbo come mostrato di seguito:
INSERT INTO table1 (uid, col_b) VALUES(4, 4);
Ora inserisci un'altra riga senza impostare uid
INSERT INTO table1 (col_b) VALUES(3);
La query non ha esito negativo, passa a 5:
+-----+-------+
| uid | col_b |
+-----+-------+
| 1 | 1 |
| 2 | 2 |
| 4 | 4 |
| 5 | 3 |
+-----+-------+
Il test è stato eseguito su MySQL 5.6.33, per Linux (x86_64) e PostgreSQL 9.4.9
A partire da Postgres 10, sono supportate anche le colonne di identità definite dallo standard SQL:
create table foo
(
id integer generated always as identity
);
crea una colonna di identità che non può essere ignorata se non esplicitamente richiesto. Il seguente inserimento fallirà con una colonna definita come generated always
:
insert into foo (id)
values (1);
Questo può tuttavia essere annullato:
insert into foo (id) overriding system value
values (1);
Quando si utilizza l'opzione, generated by default
si tratta essenzialmente dello stesso comportamento dell'implementazione esistente serial
:
create table foo
(
id integer generated by default as identity
);
Quando un valore viene fornito manualmente, anche la sequenza sottostante deve essere regolata manualmente, lo stesso di una serial
colonna.
Una colonna identità non è una chiave primaria per impostazione predefinita (proprio come una serial
colonna). Se dovrebbe essere uno, un vincolo chiave primaria deve essere definito manualmente.
Spiacenti, per riproporre una vecchia domanda, ma questa è stata la prima domanda / risposta Stack Overflow che è emersa su Google.
Questo post (che è arrivato per primo su Google) parla dell'utilizzo della sintassi più aggiornata per PostgreSQL 10: https://blog.2ndquadrant.com/postgresql-10-identity-columns/
che sembra essere:
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
);
Spero che aiuti :)
GENERATED … AS IDENTITY
comandi sono SQL standard. Aggiunto per la prima volta in SQL: 2003 , quindi chiarito in SQL: 2008 . Vedi le funzioni # T174 e F386 e T178.
Devi fare attenzione a non inserire direttamente nel tuo SERIAL o campo sequenza, altrimenti la tua scrittura fallirà quando la sequenza raggiunge il valore inserito:
-- 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;
Nel contesto della domanda posta e in risposta al commento di @ sereja1c, la creazione SERIAL
implicitamente crea sequenze, quindi per l'esempio sopra-
CREATE TABLE foo (id SERIAL,bar varchar);
CREATE TABLE
creerebbe implicitamente una sequenza foo_id_seq
per la colonna seriale foo.id
. Pertanto, SERIAL
[4 byte] è utile per la sua facilità d'uso a meno che non sia necessario un tipo di dati specifico per il proprio ID.
In questo modo funzionerà sicuramente, spero che aiuti:
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');
Puoi controllare questo i dettagli nel prossimo link: http://www.postgresqltutorial.com/postgresql-serial/
Da PostgreSQL 10
CREATE TABLE test_new (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
payload text
);