Clé primaire SQLite sur plusieurs colonnes


Réponses:


806

Selon la documentation , c'est

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

3
Eh bien, c'est vrai, mais selon la documentation, CREATE TABLE quelque chose (colonne1 PRIMARY KEY, colonne2 PRIMARY KEY); devrait aussi être possible, mais ce n’est pas le cas.
Yar

6
@Yar Les documents disent "S'il y a plus d'une clause PRIMARY KEY dans une seule instruction CREATE TABLE, c'est une erreur." Oui, les diagrammes de chemin de fer peuvent indiquer que cela est également valable, mais le texte ci-dessous précise que ce n'est pas le cas.
Brian Campbell

10
N'oubliez pas d'ajouter la partie PRIMARY KEY (colonne1, colonne2) à la fin comme dans cette réponse. Si vous essayez de l'ajouter après la définition de column2, vous obtiendrez une erreur de syntaxe .
vovahost

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

La clé primaire n'impose-t-elle pas un NOT NULL?
pratnala

23
@pratnala En SQL standard, oui. Dans SQLite, NULLest autorisé dans les clés primaires. Cette réponse souligne que si vous voulez un comportement plus standard, vous devez ajouter le NOT NULLvous - même. Ma réponse est juste la syntaxe très basique d'une clé primaire multi-colonnes.
Brian Campbell

42

Oui. Mais n'oubliez pas qu'une telle clé primaire autorise NULLplusieurs fois les valeurs dans les deux colonnes.

Créez une table comme telle:

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

Maintenant, cela fonctionne sans aucun avertissement:

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

Y a-t-il une référence à la raison d'un tel comportement? Quelle serait une bonne façon de vider plusieurs lignes dans la base de données et de supprimer les doublons, même s'ils en contiennent NULL?
Pastafarianist

4
@Pastafarianist sqlite.org/lang_createtable.html - "Selon la norme SQL, PRIMARY KEY devrait toujours impliquer NOT NULL. Malheureusement, en raison d'un bogue dans certaines versions antérieures, ce n'est pas le cas dans SQLite. [...] NULL les valeurs sont considérées comme distinctes de toutes les autres valeurs, y compris les autres valeurs NULL. "
L'incroyable

Oui, dans SQL NULL, comparez toujours false. Pour cette raison, la théorie relationnelle exclut spécifiquement NULL comme valeur de tout composant clé. SQLite, cependant, est une pratique relationnelle. Il semble que les auteurs aient choisi d'autoriser de manière pragmatique les clés multiples mais pas "égales". De toute évidence, il est préférable de ne pas autoriser les valeurs NULL comme valeurs clés.
holdenweb

32

Basique:

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

Si vos colonnes sont des clés étrangères d'autres tables (cas courant):

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

Les champs de clé primaire doivent être déclarés non nuls (ce n'est pas standard car la définition d'une clé primaire est qu'elle doit être unique et non nulle). Mais ci-dessous est une bonne pratique pour toutes les clés primaires multi-colonnes dans n'importe quel SGBD.

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

11

Depuis la version 3.8.2 de SQLite, une alternative aux spécifications explicites NOT NULL est la spécification "WITHOUT ROWID": [ 1 ]

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

Les tables "SANS ROWID" ont des avantages potentiels en termes d'efficacité, donc une alternative moins verbeuse à considérer est:

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

Par exemple, à l'invite sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2


Pour quiconque lit ceci de nos jours: WITHOUT ROWIDa des implications supplémentaires, et il ne devrait pas être utilisé comme alternative à l'écriture à NOT NULLcôté de votre clé primaire.
shadowtalker


2

PRIMARY KEY (id, name)n'a pas fonctionné pour moi. L'ajout d'une contrainte a fait le travail à la place.

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


1

Le code suivant crée une table avec 2 colonnes comme clé primaire dans SQLite.

SOLUTION:

CREATE TABLE IF NOT EXISTS users (id TEXT NOT NULL, name TEXT NOT NULL, pet_name TEXT, PRIMARY KEY (id, name))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.