Chave primária sqlite em várias colunas

Respostas:

805

De acordo com a documentação , é

CREATE TABLE something (
  column1, 
  column2, 
  column3, 
  PRIMARY KEY (column1, column2)
);
Brian Campbell
fonte
3
Bem, isso está certo, mas de acordo com a documentação, CREATE TABLE alguma coisa (coluna1 PRIMARY KEY, coluna2 PRIMARY KEY); deve ser possível também, mas não é.
Yar
6
@Yar Os documentos dizem "Se houver mais de uma cláusula PRIMARY KEY em uma única instrução CREATE TABLE, é um erro." Sim, os diagramas ferroviários podem indicar que também é válido, mas o texto abaixo esclarece que não é.
Brian Campbell
10
Lembre-se de adicionar a parte PRIMARY KEY (coluna1, coluna2) no final, como nesta resposta. Se você tentar adicioná-lo após a definição da coluna2, receberá um erro de sintaxe .
vovahost 7/02
159
CREATE TABLE something (
  column1 INTEGER NOT NULL,
  column2 INTEGER NOT NULL,
  value,
  PRIMARY KEY ( column1, column2)
);
xiwok
fonte
A Chave Primária não impõe um NOT NULL?
Pratnala
23
@pratnala No SQL padrão, sim. No SQLite, NULLé permitido em chaves primárias. Esta resposta enfatiza que, se você quiser um comportamento mais padrão, precisará adicionar NOT NULLvocê mesmo. Minha resposta é apenas a sintaxe básica de uma chave primária de várias colunas.
Brian Campbell
42

Sim. Mas lembre-se de que essa chave primária permite NULLvalores nas duas colunas várias vezes.

Crie uma tabela como tal:

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

Agora isso funciona sem nenhum 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
fonte
Existe alguma referência à razão de tal comportamento? Qual seria uma boa maneira de despejar várias linhas no banco de dados e ainda remover duplicatas, mesmo que elas contenham NULL?
precisa
4
@Pastafarianist sqlite.org/lang_createtable.html - "De acordo com o padrão SQL, PRIMARY KEY sempre deve implicar NOT NULL. Infelizmente, devido a um erro em algumas versões anteriores, esse não é o caso no SQLite. [...] valores são considerados distintos de todos os outros valores, incluindo outros NULLs ".
A incrível Jan
Sim, em SQL NULLs sempre compare false. Por esse motivo, a teoria relacional exclui especificamente NULL como o valor de qualquer componente-chave. SQLite, no entanto, é uma prática relacional. Parece que os autores optaram por permitir pragmaticamente as chaves múltiplas, mas não as "iguais". Claramente, é preferível não permitir NULLs como valores-chave.
holdenweb
31

Básico:

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

Se suas colunas são chaves estrangeiras de outras tabelas (caso comum):

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

Os campos da chave primária devem ser declarados como não nulos (isso não é padrão, pois a definição de uma chave primária é que ela deve ser exclusiva e não nula). Mas abaixo está uma boa prática para todas as chaves primárias de várias colunas em qualquer DBMS.

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

Desde a versão 3.8.2 do SQLite, uma alternativa às especificações NOT NULL explícitas é a especificação "SEM ROWID": [ 1 ]

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

As tabelas "SEM ROWID" têm vantagens potenciais de eficiência, portanto, uma alternativa menos detalhada a considerar é:

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

Por exemplo, no prompt do sqlite3: sqlite> insert into t values(1,null,3); Error: NOT NULL constraint failed: t.c2

pico
fonte
Para quem lê isso hoje em dia: WITHOUT ROWIDtem implicações adicionais e não deve ser usado como uma alternativa à escrita NOT NULLao lado da sua chave primária.
shadowtalker
2

De outra maneira, você também pode criar a chave primária de duas colunas unique e a chave de incremento automáticoprimary . Assim: https://stackoverflow.com/a/6157337

ElonChan
fonte
Era exatamente isso que eu procurava. Obrigado!
Swadhikar C 22/02/19
2

PRIMARY KEY (id, name)não funcionou para mim. A adição de uma restrição fez o trabalho.

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

Choxmi
fonte
1

O código a seguir cria uma tabela com 2 colunas como chave primária no SQLite.

SOLUÇÃO:

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