Klucz podstawowy Sqlite w wielu kolumnach


Odpowiedzi:


805

Zgodnie z dokumentacją jest to

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

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

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

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

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

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


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

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


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))
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.