синтаксис внешнего ключа postgresql

122

У меня есть 2 таблицы, как вы увидите в моем коде posgresql ниже. В первой таблице student есть 2 столбца: один для student_name, а другой student_id, который является первичным ключом. Во второй моей таблице, называемой тестами, есть 4 столбца: один для subject_id, один для subject_name, а затем один для студента с наивысшим баллом по предмету, который является наивысшимStudent_id. Я пытаюсь сделать highStudent_id ссылкой на student_id в моей таблице студентов. Это код, который у меня ниже, я не уверен, правильный ли синтаксис:

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

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

синтаксис highestStudent_id SERIAL REFERENCES studentsправильный? потому что я видел другого какhighestStudent_id REFERENCES students(student_id))

Каким будет правильный способ создания внешнего ключа в postgresql, пожалуйста?

Хамза
источник
4
Да, синтаксис «правильный». Однако столбец FK не следует определять так, как serialего следует определять как integer. serialне является «реальным» типом данных, это сокращение для
заполнения
Если FK ссылается на первичный ключ, столбцы не нужны. Если FK ссылается на альтернативный ключ, необходимы столбцы.
jarlh
1
Ваш внешний ключ ссылается на таблицу "player". Похоже, у вас нет стола с именем "игроки".
Майк Шерилл 'Cat Recall'
@Mike Sherrill 'Cat Вспомните, извините, моя ошибка я имел в виду целое число highStudent_id ССЫЛКИ студенты
Хамза

Ответы:

251

Предполагая эту таблицу:

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

Существует четыре различных способа определения внешнего ключа (при работе с PK с одним столбцом), и все они приводят к одному и тому же ограничению внешнего ключа:

  1. Встроенный без упоминания целевого столбца:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students
    );
    
  2. В строке с упоминанием целевого столбца:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students (student_id)
    );
    
  3. Вне линии внутри 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. Отдельным alter tableзаявлением:

    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);
    

Какой из них вы предпочтете - дело вкуса. Но вы должны быть последовательны в своих сценариях. Последние два оператора - единственный вариант, если у вас есть внешние ключи, ссылающиеся на PK, который состоит из более чем одного столбца - вы не можете определить FK «встроенный» в этом случае, напримерforeign key (a,b) references foo (x,y)

Только версии 3) и 4) дадут вам возможность определить собственное имя для ограничения FK, если вам не нравятся сгенерированные системой из Postgres.


Тип serialданных на самом деле не является типом данных. Это всего лишь сокращенная запись, определяющая значение по умолчанию для столбца, взятого из последовательности. Таким образом, любой столбец, ссылающийся на столбец, определенный как, serialдолжен быть определен с использованием соответствующего базового типа integer(или bigintдля bigserialстолбцов)

a_horse_with_no_name
источник
Эта ссылка ( postgresqltutorial.com/postgresql-foreign-key ) показывает другой способ сделать то, что вы сказали, можно сделать только с помощью команды 'constraint' в пунктах 3 и 4. А как насчет того, чтобы поставить FOREIGN KEY перед FK? Похоже, когда мы это делаем, нам не нужно объявлять тип переменной?
словам