AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 132029
Accepted
Hassan Baig
Hassan Baig
Asked: 2016-03-12 17:53:47 +0800 CST2016-03-12 17:53:47 +0800 CST 2016-03-12 17:53:47 +0800 CST

Como adicionar uma coluna com uma restrição de chave estrangeira a uma tabela que já existe?

  • 772

Tenho as seguintes tabelas,

CREATE TABLE users (id int PRIMARY KEY);

-- already exists with data
CREATE TABLE message ();

Como faço para alterar messagesa tabela de tal forma que,

  1. uma nova coluna chamada senderé adicionada a ela
  2. onde senderé uma chave estrangeira referenciando a userstabela

Isso não funcionou

# ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
ERROR:  column "sender" referenced in foreign key constraint does not exist

Essa instrução também não cria a coluna?

postgresql foreign-key
  • 4 4 respostas
  • 78021 Views

4 respostas

  • Voted
  1. Best Answer
    Vérace
    2016-03-12T19:30:48+08:002016-03-12T19:30:48+08:00

    Você só precisa adicionar outra etapa - na verdade, o PostgreSQL já está lhe dizendo que: column "sender" referenced in foreign key constraint does not exist.

    A coluna FOREIGN KEY(aka ) já deve existir para torná-la um .parentFK

    Eu fiz o seguinte (a partir daqui e da documentação ). Observe que a coluna pai precisa ter uma UNIQUErestrição (ou ser o PRIMARY KEY), mas não precisa ser NOT NULL. Isso ocorre porque NULLs não são iguais entre si, nem são iguais a qualquer outra coisa - cada um NULLé considerado UNIQUEem seu próprio direito!

    CREATE TABLE x(a INT UNIQUE NOT NULL);
    
    CREATE TABLE y(b INT);
    
    ALTER TABLE y ADD COLUMN c INT NOT NULL
    CONSTRAINT y_x_fk_c REFERENCES x (a)   -- if x (a) doens't exist, this will fail!
    ON UPDATE CASCADE ON DELETE CASCADE;  -- or other Referential Integrity Action
    

    Alguns pontos a serem observados (veja o violino aqui ) - uma tentativa de inserir um valor em y (c) que não está em x (a) falha e o nome da restrição é fornecido na mensagem de erro.

    O violino tem NOT NULLrestrições em x (a) e em y (c). A menos que eu tenha um motivo realmente convincente , sempre declaro minhas colunas como NOT NULL- isso ajuda o otimizador e reduz o potencial de confusão/erro. Você pode experimentar o violino para ver o que acontece quando você deixa de fora o NOT NULL(s) campo(s) - o comportamento nem sempre é intuitivamente óbvio!

    SEMPRE dê nomes significativos às suas chaves estrangeiras. Ser informado de que a chave "SYS_C00308108" está sendo violada não é muito útil. Veja o violino aqui para o comportamento do Oracle sob essas circunstâncias, o nome da chave irá variar de violino para violino, mas é uma string arbitrária começando com SYS_... (vem após o nome da tabela gerado pelo dbfiddle longo).

    Evan Carroll em sua resposta aqui acredita que nomes gerados automaticamente estão OK - eu mostrei por que isso não é uma boa ideia para o Oracle (pelo menos até 18c), mas também sinto que não é uma boa ideia para o PostgreSQL - problemas potenciais de portabilidade, se nada mais.

    Eu gostaria de dar crédito a Evan Carroll por apontar que a adição do novo campo e a FOREIGN KEYcriação e o CONSTRAINT(com o nome especificado) podem ser adicionados em uma etapa e não em duas etapas como eu disse originalmente) - então, por favor, dê-lhe crédito por isso se você sentir vontade de me votar - eu entro em mais detalhes no entanto.

    Considerando a afirmação em sua pergunta:

    ALTER TABLE message ADD FOREIGN KEY (sender) REFERENCES users;
    

    Seria "legal" se o RDBMS pudesse criar automaticamente o campo desejado com o tipo de dados correspondente ao campo referenciado.

    Tudo o que eu diria é que alterar o DDL é (ou pelo menos deveria ser) uma operação raramente usada e não algo que você gostaria de fazer regularmente. Também corre o risco de adicionar a uma documentação já bastante substancial.

    Pelo menos o PostgreSQL tenta fazer algo razoável - ele concatena o nome da tabela, o FOREIGN KEYnome do campo e fkey. Além disso, quando você mesmo nomear a restrição, a mensagem de erro será adicionada DETAIL: Key (c)=(7) is not present in table "x".para fornecer algo que possa fazer sentido para um ser humano (diferente do Oracle - veja o final do violino do PostgreSQL ).

    • 31
  2. Evan Carroll
    2018-03-29T09:37:15+08:002018-03-29T09:37:15+08:00

    Não sei por que todos estão dizendo que você precisa fazer isso em duas etapas. Na verdade, você não . Você tentou adicionar um FOREIGN KEYque assume, por design, que a coluna está lá e lança esse erro se a coluna não estiver lá. Se você adicionar o COLUMN, poderá torná-lo explicitamente FOREIGN KEYna criação com REFERENCES,

    ALTER TABLE message
      ADD COLUMN sender INT
      REFERENCES users;  -- or REFERENCES table(unique_column)
    

    Vai funcionar bem. Você pode ver a sintaxe de ALTER TABLEaqui,

    ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
    action [, ... ]
    

    Com "ação" como,

    ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
    

    Esses exemplos estão até nos documentos,

    ALTER TABLE distributors
      ADD CONSTRAINT distfk
      FOREIGN KEY (address)
      REFERENCES addresses (address);
    
    ALTER TABLE distributors
      ADD CONSTRAINT distfk
      FOREIGN KEY (address)
      REFERENCES addresses (address)
      NOT VALID;
    

    Mas tudo isso não é necessário porque podemos confiar na autonomeação e na resolução da chave primária (se apenas o nome da tabela for especificado, você estará referenciando a chave primária).

    • 18
  3. Ashok Allu
    2018-03-29T09:08:34+08:002018-03-29T09:08:34+08:00

    CASE1: Se você precisar criar uma chave estrangeira ao criar uma nova tabela

    CREATE TABLE table1(
    id SERIAL PRIMARY KEY,
    column1 varchar(n) NOT NULL,
    table2_id SMALLINT REFERENCES table2(id)
    ); 
    

    Os comandos acima criarão uma tabela com o nome 'table1' e três colunas denominadas 'id'(chave primária), 'column1', 'table2_id'(chave estrangeira da tabela1 que faz referência à coluna id da tabela2).

    DATATYPE 'serial' fará com que a coluna que usa esse tipo de dados seja uma coluna gerada automaticamente, ao inserir valores na tabela você não precisa mencionar essa coluna, ou pode dar 'default' sem aspas no lugar do valor.

    Uma coluna de chave primária é sempre adicionada ao índice da tabela com o valor 'tablename_pkey'.

    Se uma chave estrangeira for adicionada no momento da criação da tabela, uma CONSTRAINT será adicionada com o padrão '(present_table_name)_(foreign_key_id_name)_fkey'.

    Ao adicionar uma chave estrangeira, temos que inserir a palavra-chave 'REFERENCES' ao lado do nome da coluna porque queremos informar ao postgres que esta coluna faz referência a uma tabela e, ao lado de referências, devemos fornecer a tabela para referência e entre colchetes, fornecer o nome da coluna da tabela referenciada, geralmente as chaves estrangeiras são fornecidas como colunas de chave primária.

    CASO 2: Se você deseja chave estrangeira para uma tabela existente na coluna existente

    ALTER TABLE table1
    ADD CONSTRAINT table1_table2_id_id_fkey
    FOREIGN KEY (table2_id) REFERENCES table2(id);
    

    NOTA: colchetes '()' após FOREIGN KEY e REFERENCES tabel2 são obrigatórios ou então o postgres lançará um erro.

    • 1
  4. XIN WANG
    2020-04-07T03:00:09+08:002020-04-07T03:00:09+08:00

    Eu sei o problema. Os nomes das colunas são diferentes. Talvez em uma coluna, haja um espaço adicionado após o nome da coluna, portanto, certifique-se cuidadosamente de que os nomes das colunas tenham o mesmo nome.

    • 1

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve