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


Antworten:


805

Laut Dokumentation ist es

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

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)
);

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

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
);

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)
)
;

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


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

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))


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))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.