sintaxe da chave estrangeira do postgresql

122

Eu tenho 2 tabelas, como você verá no meu código posgresql abaixo. A primeira tabela de alunos possui 2 colunas, uma para student_name e a outra student_id, que é a chave primária. Na minha segunda tabela chamada testes, ela possui 4 colunas, uma para subject_id, uma para o subject_name e, em seguida, uma para um aluno com a pontuação mais alta em uma disciplina com o maiorStudent_id. estou tentando fazer com que o maximumStudent_id se refira a student_id na minha tabela de alunos. Este é o código que tenho abaixo, não tenho certeza se a sintaxe está correta:

CREATE TABLE students ( student_id SERIAL PRIMARY KEY,
                 player_name TEXT);

CREATE TABLE tests ( subject_id SERIAL,
                   subject_name,
                   highestStudent_id SERIAL REFERENCES students);

a sintaxe está highestStudent_id SERIAL REFERENCES studentscorreta? porque eu vi outro comohighestStudent_id REFERENCES students(student_id))

Qual seria a maneira correta de criar a chave estrangeira no postgresql, por favor?

Hamza
fonte
4
Sim, a sintaxe está "correta". No entanto, a coluna FK não deve ser definida como serialdeve ser definida como integer. serialnão é um tipo de dados "real", é uma mão curta para preencher o valor padrão da sequência
a_horse_with_no_name
Se o FK fizer referência a uma chave primária, nenhuma coluna será necessária. Se o FK referenciar uma chave alternativa, serão necessárias colunas.
jarlh
1
Sua chave estrangeira faz referência à tabela "players". Você não parece ter uma mesa chamada "players".
Mike Sherrill 'Cat Recall'
@Mike Sherrill 'Cat Lembre-se, desculpe, meu erro foi o número mais altoStudent_id inteiro REFERENCES alunos
Hamza

Respostas:

249

Assumindo esta tabela:

CREATE TABLE students 
( 
  student_id SERIAL PRIMARY KEY,
  player_name TEXT
);

Existem quatro maneiras diferentes de definir uma chave estrangeira (ao lidar com uma única coluna PK) e todas elas levam à mesma restrição de chave estrangeira:

  1. Inline sem mencionar a coluna de destino:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students
    );
  2. De acordo com a menção da coluna de destino:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students (student_id)
    );
  3. Fora de linha dentro de create table:

    CREATE TABLE tests 
    ( 
      subject_id SERIAL,
      subject_name text,
      highestStudent_id integer, 
      constraint fk_tests_students
         foreign key (highestStudent_id) 
         REFERENCES students (student_id)
    );
  4. Como uma alter tabledeclaração separada :

    CREATE TABLE tests 
    ( 
      subject_id SERIAL,
      subject_name text,
      highestStudent_id integer
    );
    
    alter table tests 
        add constraint fk_tests_students
        foreign key (highestStudent_id) 
        REFERENCES students (student_id);

Qual você prefere é uma questão de gosto. Mas você deve ser consistente em seus scripts. As duas últimas instruções são a única opção se você tiver chaves estrangeiras que referenciam uma PK que consiste em mais de uma coluna - não é possível definir a FK "inline" nesse caso, por exemplo,foreign key (a,b) references foo (x,y)

Somente as versões 3) e 4) permitem definir seu próprio nome para a restrição FK se você não gostar dos nomes gerados pelo sistema no Postgres.


O serialtipo de dados não é realmente um tipo de dados. É apenas uma notação curta que define um valor padrão para a coluna retirada de uma sequência. Portanto, qualquer coluna que faça referência a uma coluna definida como serialdeve ser definida usando o tipo de base apropriado integer(ou bigintpara bigserialcolunas)

um cavalo sem nome
fonte
Este link ( postgresqltutorial.com/postgresql-foreign-key ) mostra outra maneira de fazer o que você disse que só pode ser feito com o comando 'constraint' em 3 e 4. Além disso, que tal colocar FOREIGN KEY antes do FK? Parece que quando fazemos isso, não precisamos declarar o tipo de variável?
wordsforthewise