SQLite-Primärschlüssel für mehrere Spalten

619

Wie lautet die Syntax zum Angeben eines Primärschlüssels für mehr als eine Spalte in SQLITE?

Bogdan Gavril MSFT
quelle
14
Dies wird auch zusammengesetzter Schlüssel en.wikipedia.org/wiki/Compound_key
OneWorld
6
@OneWorld Oder zusammengesetzter Schlüssel, wenn eine der Spalten selbst kein Schlüssel ist.
Michael

Antworten:

805

Laut Dokumentation ist es

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);
Brian Campbell
quelle
3
Nun, das ist richtig, aber laut Dokumentation CREATE TABLE etwas (Spalte1 PRIMARY KEY, Spalte2 PRIMARY KEY); sollte auch möglich sein, ist es aber nicht.
Yar
6
@Yar In den Dokumenten heißt es: "Wenn eine einzelne CREATE TABLE-Anweisung mehr als eine PRIMARY KEY-Klausel enthält, liegt ein Fehler vor." Ja, die Eisenbahndiagramme könnten darauf hinweisen, dass dies ebenfalls gültig ist, aber der folgende Text verdeutlicht, dass dies nicht der Fall ist.
Brian Campbell
10
Denken Sie daran, den Teil PRIMARY KEY (Spalte1, Spalte2) am Ende wie in dieser Antwort hinzuzufügen . Wenn Sie versuchen, es nach der Definition von column2 hinzuzufügen, wird ein Syntaxfehler angezeigt .
Vovahost
159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);
xiwok
quelle
Erlegt der Primärschlüssel nicht NOT NULL auf?
Pratnala
23
@pratnala In Standard-SQL ja. In SQLite NULList in Primärschlüsseln zulässig. Diese Antwort betont, dass Sie das NOT NULLSelbst hinzufügen müssen, wenn Sie mehr Standardverhalten wünschen . Meine Antwort ist nur die grundlegende Syntax für einen mehrspaltigen Primärschlüssel.
Brian Campbell
42

Ja. Denken Sie jedoch daran, dass ein solcher Primärschlüssel NULLWerte in beiden Spalten mehrmals zulässt .

Erstellen Sie eine Tabelle als solche:

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

Dies funktioniert nun ohne Vorwarnung:

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
jsmarkus
quelle
Gibt es einen Hinweis auf den Grund eines solchen Verhaltens? Was wäre ein guter Weg, um mehrere Zeilen in der Datenbank zu sichern und trotzdem Duplikate zu entfernen, selbst wenn sie enthalten NULL?
Pastafarianist
4
@Pastafarianist sqlite.org/lang_createtable.html - "Gemäß dem SQL-Standard sollte PRIMARY KEY immer NOT NULL implizieren. Leider ist dies aufgrund eines Fehlers in einigen frühen Versionen in SQLite nicht der Fall. [...] NULL Werte werden als von allen anderen Werten verschieden angesehen, einschließlich anderer NULL-Werte. "
Der unglaubliche
Ja, in SQL vergleichen NULL-Werte immer false. Aus diesem Grund schließt die relationale Theorie NULL als Wert einer Schlüsselkomponente ausdrücklich aus. SQLite ist jedoch eine relationale Praxis. Es scheint, dass die Autoren sich dafür entschieden haben, die mehreren, aber nicht "gleichen" Schlüssel pragmatisch zuzulassen. Es ist natürlich vorzuziehen, NULL-Werte nicht als Schlüsselwerte zuzulassen.
Holdenweb
31

Basic :

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

Wenn Ihre Spalten Fremdschlüssel anderer Tabellen sind (häufiger Fall):

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
);
compte14031879
quelle
14

Primärschlüsselfelder sollten als nicht null deklariert werden (dies ist kein Standard, da die Definition eines Primärschlüssels lautet, dass er eindeutig und nicht null sein muss). Im Folgenden finden Sie eine bewährte Methode für alle mehrspaltigen Primärschlüssel in einem DBMS.

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

Seit Version 3.8.2 von SQLite ist die Spezifikation "WITHOUT ROWID" eine Alternative zu expliziten NOT NULL-Spezifikationen: [ 1 ]

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

"WITHOUT ROWID" -Tabellen bieten potenzielle Effizienzvorteile. Eine weniger ausführliche Alternative ist daher:

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

Zum Beispiel an der Eingabeaufforderung sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2

Gipfel
quelle
Für jeden, der dies heutzutage liest: WITHOUT ROWIDhat zusätzliche Auswirkungen und sollte nicht als Alternative zum Schreiben NOT NULLneben Ihrem Primärschlüssel verwendet werden.
Shadowtalker
2

Auf andere Weise können Sie auch den zweispaltigen Primärschlüssel unique und den Auto-Inkrement- Schlüssel festlegenprimary . Einfach so: https://stackoverflow.com/a/6157337

ElonChan
quelle
Genau danach habe ich gesucht. Vielen Dank!
Swadhikar C
2

PRIMARY KEY (id, name)hat bei mir nicht funktioniert. Das Hinzufügen einer Einschränkung hat den Job stattdessen erledigt.

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

Choxmi
quelle
1

Der folgende Code erstellt eine Tabelle mit 2 Spalten als Primärschlüssel in SQLite.

LÖSUNG:

CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT NOT NULL, pet_name TEXT, PRIMARY KEY (id, name))
Naveen Kumar V.
quelle