Chiave primaria SQLite su più colonne


Risposte:


805

Secondo la documentazione , lo è

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);

3
Bene, questo è giusto, ma secondo la documentazione, CREATE TABLE qualcosa (column1 PRIMARY KEY, column2 PRIMARY KEY); dovrebbe essere possibile anche, ma non lo è.
Anno

6
@Yar I documenti dicono "Se c'è più di una clausola PRIMARY KEY in una singola istruzione CREATE TABLE, si tratta di un errore." Sì, i diagrammi ferroviari potrebbero indicare che è valido anche, ma il testo qui sotto chiarisce che non lo è.
Brian Campbell,

10
Ricorda di aggiungere la parte PRIMARY KEY (colonna1, colonna2) alla fine come in questa risposta. Se provi ad aggiungerlo dopo la definizione di column2 otterrai un errore di sintassi .
vovahost

159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);

La chiave primaria non impone un NOT NULL?
pratnala,

23
@pratnala In SQL standard, sì. In SQLite, NULLè consentito nelle chiavi primarie. Questa risposta sottolinea che se vuoi un comportamento più standard, devi aggiungere NOT NULLte stesso. La mia risposta è solo la sintassi di base per una chiave primaria multi-colonna.
Brian Campbell,

42

Sì. Ma ricorda che tale chiave primaria consente NULLpiù volte valori in entrambe le colonne.

Crea una tabella come tale:

    sqlite> CREATE TABLE something (
column1, column2, value, PRIMARY KEY (column1, column2));

Ora funziona senza alcun preavviso:

sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> insert into something (value) VALUES ('bla-bla');
sqlite> select * from something;
NULL|NULL|bla-bla
NULL|NULL|bla-bla

C'è qualche riferimento alla ragione di tale comportamento? Quale sarebbe un buon modo per scaricare diverse righe nel database e rimuovere comunque i duplicati, anche se contengono NULL?
Pastafarista

4
@Pastafarianist sqlite.org/lang_createtable.html - "Secondo lo standard SQL, PRIMARY KEY dovrebbe sempre implicare NOT NULL. Sfortunatamente, a causa di un bug in alcune versioni precedenti, questo non è il caso di SQLite. [...] NULL i valori sono considerati distinti da tutti gli altri valori, inclusi altri NULL. "
L'incredibile gennaio

Sì, in SQL NULL confronta sempre false. Per questo motivo, la teoria relazionale esclude specificamente NULL come valore di qualsiasi componente chiave. SQLite, tuttavia, è pratica relazionale. Sembra che gli autori abbiano scelto di consentire pragmaticamente le chiavi multiple ma non "uguali". Chiaramente è preferibile non consentire NULL come valori chiave.
holdenweb,

31

Di base:

CREATE TABLE table1 (
    columnA INTEGER NOT NULL,
    columnB INTEGER NOT NULL,
    PRIMARY KEY (columnA, columnB)
);

Se le tue colonne sono chiavi esterne di altre tabelle (caso comune):

CREATE TABLE table1 (
    table2_id INTEGER NOT NULL,
    table3_id INTEGER NOT NULL,
    FOREIGN KEY (table2_id) REFERENCES table2(id),
    FOREIGN KEY (table3_id) REFERENCES table3(id),
    PRIMARY KEY (table2_id, table3_id)
);

CREATE TABLE table2 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

CREATE TABLE table3 (
    id INTEGER NOT NULL,
    PRIMARY KEY id
);

14

I campi chiave primaria devono essere dichiarati come non nulli (ciò non è standard poiché la definizione di chiave primaria è che deve essere univoca e non nulla). Di seguito è una buona pratica per tutte le chiavi primarie multi-colonna in qualsiasi DBMS.

create table foo
(
  fooint integer not null
  ,foobar string not null
  ,fooval real
  ,primary key (fooint, foobar)
)
;

11

Dalla versione 3.8.2 di SQLite, un'alternativa alle specifiche esplicite NOT NULL è la specifica "WITHOUT ROWID": [ 1 ]

NOT NULL is enforced on every column of the PRIMARY KEY
in a WITHOUT ROWID table.

Le tabelle "WITHOUT ROWID" presentano potenziali vantaggi in termini di efficienza, quindi un'alternativa meno dettagliata da considerare è:

CREATE TABLE t (
  c1, 
  c2, 
  c3, 
  PRIMARY KEY (c1, c2)
 ) WITHOUT ROWID;

Ad esempio, al prompt di sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2


Per chiunque legga questo al giorno d'oggi: WITHOUT ROWIDha implicazioni aggiuntive e non dovrebbe essere usato come alternativa alla scrittura NOT NULLaccanto alla chiave primaria.
Shadowtalker


2

PRIMARY KEY (id, name)non ha funzionato per me. L'aggiunta di un vincolo ha fatto invece il lavoro.

CREATE TABLE IF NOT EXISTS customer (id INTEGER, name TEXT, user INTEGER, CONSTRAINT PK_CUSTOMER PRIMARY KEY (user, id))


1

Il codice seguente crea una tabella con 2 colonne come chiave primaria in SQLite.

SOLUZIONE:

CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT NOT NULL, pet_name TEXT, PRIMARY KEY (id, name))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.