Klucz podstawowy Sqlite w wielu kolumnach

Odpowiedzi:

805

Zgodnie z dokumentacją jest to

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);
Brian Campbell
źródło
3
Cóż, to prawda, ale zgodnie z dokumentacją, UTWÓRZ coś w tabeli (kolumna 1 KLUCZ PODSTAWOWY, kolumna 2 KLUCZ PODSTAWOWY); powinno być możliwe, ale tak nie jest.
Yar
6
@Yar Dokumenty mówią „Jeśli w jednej instrukcji CREATE TABLE występuje więcej niż jedna klauzula PRIMARY KEY, oznacza to błąd”. Tak, diagramy kolejowe również mogą wskazywać, że jest to poprawne, ale poniższy tekst wyjaśnia, że ​​tak nie jest.
Brian Campbell
10
Pamiętaj, aby dodać KLUCZ PODSTAWOWY (kolumna 1, kolumna 2) na końcu, jak w tej odpowiedzi. Jeśli spróbujesz dodać go po definicji kolumny 2, pojawi się błąd składniowy .
vovahost
159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);
Xiwok
źródło
Czy klucz podstawowy nie narzuca NOT NULL?
pratnala
23
@pratnala W standardowym języku SQL tak. W SQLite NULLjest dozwolone w kluczach podstawowych. Ta odpowiedź podkreśla, że ​​jeśli chcesz bardziej standardowych zachowań, musisz dodać NOT NULLsiebie. Moja odpowiedź to tylko bardzo podstawowa składnia dla klucza głównego z wieloma kolumnami.
Brian Campbell
42

Tak. Pamiętaj jednak, że taki klucz podstawowy dopuszcza NULLwartości w obu kolumnach wiele razy.

Utwórz tabelę jako taką:

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

Teraz działa to bez żadnego ostrzeżenia:

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
źródło
Czy jest jakieś odniesienie do przyczyny takiego zachowania? Jaki byłby dobry sposób na zrzucenie kilku wierszy w bazie danych i nadal usuwanie duplikatów, nawet jeśli zawierają NULL?
Pastafarianist
4
@Pastafarianist sqlite.org/lang_createtable.html - „Zgodnie ze standardem SQL KLUCZ PODSTAWOWY zawsze powinien oznaczać NIE NULL. Niestety, z powodu błędu w niektórych wczesnych wersjach, nie jest tak w przypadku SQLite. [...] NULL wartości są uważane za różne od wszystkich innych wartości, w tym innych wartości NULL. ”
Niesamowity
Tak, w SQL NULL zawsze porównuje się false. Z tego powodu teoria relacyjna wyklucza wartość NULL jako wartość dowolnego kluczowego komponentu. SQLite jest jednak praktyką relacyjną. Wygląda na to, że autorzy postanowili pragmatycznie zezwolić na wiele, ale nie „równych” kluczy. Oczywiście lepiej nie dopuszczać wartości NULL jako wartości kluczowych.
holdenweb,
31

Basic:

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

Jeśli twoje kolumny to klucze obce innych tabel (częsty przypadek):

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
źródło
14

Pola klucza głównego powinny być zadeklarowane jako niepuste (jest to niestandardowe, ponieważ definicja klucza podstawowego polega na tym, że musi on być unikalny, a nie pusty). Ale poniżej znajduje się dobra praktyka dla wszystkich wielokolumnowych kluczy podstawowych w dowolnym DBMS.

create table foo
(
  fooint integer not null
  ,foobar string not null
  ,fooval real
  ,primary key (fooint, foobar)
)
;
Ken Reed
źródło
11

Od wersji 3.8.2 SQLite alternatywą dla jawnych specyfikacji NOT NULL jest specyfikacja „BEZ ROWID”: [ 1 ]

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

Tabele „BEZ ROWIDA” mają potencjalne zalety w zakresie wydajności, dlatego mniej szczegółową alternatywą do rozważenia jest:

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

Na przykład po znaku zachęty sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2

szczyt
źródło
Każdy, kto czyta to w dzisiejszych czasach: WITHOUT ROWIDma dodatkowe implikacje i nie powinien być używany jako alternatywa dla pisania NOT NULLobok klucza podstawowego.
shadowtalker
2

W inny sposób, można również zrobić dwie kolumny klucza podstawowego unique i automatycznego przyrostu klucza primary. Dokładnie tak: https://stackoverflow.com/a/6157337

ElonChan
źródło
Właśnie tego szukałem. Dziękuję Ci!
Swadhikar C
2

PRIMARY KEY (id, name)nie działało dla mnie. Zamiast tego wystarczyło dodanie ograniczenia.

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

Choxmi
źródło
1

Poniższy kod tworzy tabelę z 2 kolumnami jako klucz podstawowy w SQLite.

ROZWIĄZANIE:

CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT NOT NULL, pet_name TEXT, PRIMARY KEY (id, name))
Naveen Kumar V.
źródło