Clave principal de SQLite en varias columnas

Respuestas:

806

De acuerdo con la documentación , es

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);
Brian Campbell
fuente
3
Bueno, esto es correcto, pero de acuerdo con la documentación, CREATE TABLE something (column1 PRIMARY KEY, column2 PRIMARY KEY); debería ser posible también, pero no lo es.
Yar
66
@Yar Los documentos dicen "Si hay más de una cláusula PRIMARY KEY en una sola instrucción CREATE TABLE, es un error". Sí, los diagramas ferroviarios también pueden indicar que es válido, pero el texto a continuación aclara que no lo es.
Brian Campbell
10
Recuerde agregar la parte PRIMARY KEY (column1, column2) al final como en esta respuesta. Si intenta agregarlo después de la definición de la columna 2, obtendrá un error de sintaxis .
vovahost
159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);
xiwok
fuente
¿La clave primaria no impone un NOT NULL?
pratnala
23
@pratnala En SQL estándar, sí. En SQLite, NULLestá permitido en claves primarias. Esta respuesta enfatiza que si desea un comportamiento más estándar, debe agregarlo NOT NULLusted mismo. Mi respuesta es solo la sintaxis muy básica para una clave primaria de varias columnas.
Brian Campbell
42

Si. Pero recuerde que dicha clave primaria permite NULLvalores en ambas columnas varias veces.

Crea una tabla como tal:

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

Ahora esto funciona sin previo aviso:

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
fuente
¿Hay alguna referencia a la razón de tal comportamiento? ¿Cuál sería una buena manera de volcar varias filas en la base de datos y aún eliminar duplicados, incluso si contienen NULL?
Pastafarianist
44
@Pastafarianist sqlite.org/lang_createtable.html - "De acuerdo con el estándar SQL, PRIMARY KEY siempre debe implicar NO NULL. Desafortunadamente, debido a un error en algunas versiones anteriores, este no es el caso en SQLite. [...] NULL los valores se consideran distintos de todos los demás valores, incluidos otros valores NULL ".
El increíble Jan
Sí, en SQL NULLs siempre compara false. Debido a esto, la teoría relacional excluye específicamente NULL como el valor de cualquier componente clave. SQLite, sin embargo, es una práctica relacional. Parece que los autores optaron por permitir pragmáticamente las claves múltiples pero no "iguales". Claramente, es preferible no permitir NULL como valores clave.
holdenweb
31

Básico :

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

Si sus columnas son claves foráneas de otras tablas (caso común):

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
fuente
14

Los campos de clave primaria deben declararse como no nulos (esto no es estándar ya que la definición de una clave primaria es que debe ser única y no nula). Pero a continuación se muestra una buena práctica para todas las claves primarias de varias columnas en cualquier DBMS.

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

Desde la versión 3.8.2 de SQLite, una alternativa a las especificaciones explícitas NOT NULL es la especificación "SIN ROWID": [ 1 ]

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

Las tablas "SIN ROWID" tienen ventajas potenciales de eficiencia, por lo que una alternativa menos detallada a considerar es:

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

Por ejemplo, en el indicador sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2

pico
fuente
Para cualquiera que lea esto hoy en día: WITHOUT ROWIDtiene implicaciones adicionales, y no debe usarse como una alternativa a escribir NOT NULLjunto a su clave principal.
shadowtalker
2

De otra manera, también puede hacer que la clave principal de dos columnas unique y la clave de incremento automáticoprimary . Justo así: https://stackoverflow.com/a/6157337

ElonChan
fuente
Esto es lo que estaba buscando exactamente. ¡Gracias!
Swadhikar C
2

PRIMARY KEY (id, name)no funciono para mi Agregar una restricción hizo el trabajo en su lugar.

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

Choxmi
fuente
1

El siguiente código crea una tabla con 2 columnas como clave principal en SQLite.

SOLUCIÓN:

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