PostgreSQL - inserção / atualização viola restrições de chave estrangeira

12

Eu sou novo no postgreSQL. Eu tenho 3 tabelas, uma tabela referencia as chaves primárias das outras 2 tabelas. Mas não consegui inserir dados no Table3. Veja o código abaixo:

DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
  "DataID" bigint NOT NULL DEFAULT '0',
  "AdData" integer DEFAULT NULL,
  PRIMARY KEY ("DataID")
);

DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
  "Address" numeric(20) NOT NULL DEFAULT '0',
  "Value" numeric(20) DEFAULT NULL,
  PRIMARY KEY ("Address")
);

DROP TABLE IF EXISTS Table3 CASCADE; 
CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL,   
  "Address" numeric(20) DEFAULT NULL,   
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,   
   FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);

ERRO: inserir ou atualizar a tabela "Tabela3" viola a restrição de chave estrangeira "Table3_DataID_fkey" DETALHE: Chave (DataID) = (27856) não está presente na tabela "Tabela1".

Quando tentei inserir dados nas 3 tabelas, ocorreu um erro. Consultei a documentação do postgreSQL e alterei meu código da seguinte forma: (Infelizmente, ele mostrou outro erro)

DROP TABLE Table1 CASCADE;
CREATE TABLE Table1(
  "DataID" bigint NOT NULL DEFAULT '0',
  "AdData" integer DEFAULT NULL,
  PRIMARY KEY ("DataID")
);

DROP TABLE IF EXISTS Table2 CASCADE;
CREATE TABLE Table2 (
  "Address" numeric(20) NOT NULL DEFAULT '0',
  "Value" numeric(20) DEFAULT NULL,
  PRIMARY KEY ("Address")
);

DROP TABLE IF EXISTS Table3 CASCADE; 
CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL REFERENCES Table1 ON DELETE RESTRICT,
  "Address" numeric(20) DEFAULT NULL REFERENCES Table2 ON DELETE CASCADE, 
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   PRIMARY KEY("DataID", "Address")
);

ERRO: várias chaves primárias para a tabela "Tabela3" não são permitidas. LINHA 65: PRIMARY KEY ("DataID", "Address")

Por favor me ajude ... Como posso criar a referência?

Troquei o IDas UNIQUEe removi a linha PRIMARY KEY ("ID"). Naquele momento, mostra outro erro como:

ERRO: o valor duplicado da chave viola a restrição exclusiva "Table3_pkey"

Haseena
fonte

Respostas:

17

Existem alguns problemas com suas tabelas. Vou tentar abordar as chaves estrangeiras primeiro, já que você pergunta sobre elas :)

Porém, antes disso, devemos perceber que os dois conjuntos de tabelas (os três primeiros que você criou e o segundo conjunto, que você criou após o lançamento do primeiro conjunto) são os mesmos. Obviamente, a definição de Table3em sua segunda tentativa tem sintaxe e erros lógicos, mas a idéia básica é:

CREATE TABLE table3 (   
  "ID" bigint NOT NULL DEFAULT '0',   
  "DataID" bigint DEFAULT NULL,   
  "Address" numeric(20) DEFAULT NULL,   
  "Data" bigint DEFAULT NULL,
   PRIMARY KEY ("ID"),   
   FOREIGN KEY ("DataID") REFERENCES Table1("DataID") on delete cascade on update cascade,   
   FOREIGN KEY ("Address") REFERENCES Table2("Address") on delete cascade on update cascade
);

Essa definição informa ao PostgreSQL aproximadamente o seguinte: "Crie uma tabela com quatro colunas, uma será a chave primária (PK), as outras podem ser NULL. Se uma nova linha for inserida, verifique DataIDe Address: se elas contêm um valor não NULL ( dizer 27856), em seguida, verificar Table1para DataIDe Table2para Address. Se não há tal valor desses quadros, em seguida, retornar um erro." Este último ponto que você viu primeiro:

ERROR: insert or update on table "Table3" violates foreign key constraint 
    "Table3_DataID_fkey" DETAIL: Key (DataID)=(27856) is not present in table "Table1".

Tão simples: se não houver linha Table1onde DataID = 27856, não será possível inserir essa linha Table3.

Se você precisar dessa linha, primeiro insira uma linha no Table1e DataID = 27856, em seguida, tente inseri-lo Table3. Se isso não lhe parece o que você deseja, descreva em poucas frases o que você deseja alcançar, e podemos ajudar com um bom design.


E agora sobre os outros problemas.

Você define suas PKs como

CREATE all_your_tables (
    first_column NOT NULL DEFAULT '0',   
    [...]
    PRIMARY KEY ("ID"),  

Uma chave primária significa que todos os itens nela são diferentes, ou seja, os valores são UNIQUE. Se você der uma estática DEFAULT(como '0') a uma UNIQUEcoluna, terá más surpresas o tempo todo. É isso que você recebeu na sua terceira mensagem de erro.

Além disso, '0'significa uma sequência de texto, mas não um número ( bigintou numericno seu caso). Use simplesmente 0(ou não use, como escrevi acima).

E um último ponto (posso estar errado aqui): em Table2, seu Addresscampo está definido como numeric(20). Ao mesmo tempo, é o PK da tabela. O nome da coluna e o tipo de dados sugerem que esse endereço pode ser alterado no futuro. Se isso for verdade, é uma péssima escolha para um PK. Pense no seguinte cenário: você tem um endereço '1234567890454', que tem um filho Table3semelhante

ID        DataID           Address             Data
123       3216547          1234567890454       654897564134569

Agora, esse endereço muda para algo diferente. Como você faz seu filho Table3seguir a linha pai até o novo endereço? (Existem soluções para isso, mas podem causar muita confusão.) Se esse for o seu caso, adicione uma coluna de ID à sua tabela, que não conterá nenhuma informação do mundo real, ela simplesmente servirá como um valor de identificação (ou seja, , ID) para um endereço.

dezso
fonte
Obrigado pela sua sugestão valiosa. Vou tentar um melhor design com base em suas sugestões. Agora o primeiro erro foi resolvido.
Haseena #
0

Tudo depende do que você deseja fazer com os dados.

Primeiro exemplo - você deseja ter dados consistentes em todas as tabelas, mas tenta inserir valores que não correspondem à Tabela1.

Segundo exemplo - você não deseja ter dados consistentes, mas tenta fazer outra coisa, sem saber exatamente o que. A tabela não pode ter mais de uma chave primária.

Terceiro exemplo - você ainda não sabe o que deseja alcançar e coloca restrição UNIQUE na coluna que pode ter o mesmo valor várias vezes.

Se você apenas deseja inserir seus dados, livre-se das referências de chave estrangeira no primeiro exemplo. Se você deseja ter dados consistentes em todas as tabelas - faça a limpeza dos dados e insira nas tabelas COM restrições de chave estrangeira.

tl; dr: para inserir seus dados na Tabela3 com o código do primeiro exemplo - insira valores ausentes na coluna Table1.DataID que existe na Tabela3.DataId.

BartekR
fonte