синтаксис іноземного ключа postgresql


122

У мене є дві таблиці, як ви побачите в моєму коді posgresql нижче. Студенти першої таблиці мають 2 стовпчики, один для імені студента, а інший student_id, який є первинним ключем. У моїй другій таблиці під назвою тести, вона має 4 стовпчики, один для теми_ід, один для імені предмета, потім один для студента з найбільшою оцінкою в предметі, який є найвищим Студент_ід. я намагаюся зробити так, щоб найвищий_Student_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не є "реальним" типом даних, це коротка рука для заповнення значення за замовчуванням із послідовності
a_horse_with_no_name

Якщо FK посилається на первинний ключ, стовпці не потрібні. Якщо FK посилається на альтернативний ключ, потрібні стовпці.
jarlh

1
Ваш зовнішній ключ посилається на таблицю "гравців". У вас, здається, немає таблиці під назвою "гравці".
Майк Шеррілл 'Відкликання котів'

@Mike Sherrill 'Cat Нагадаємо, вибачте, моя помилка, я мав на увазі найвищий цілий числоStudent_id РЕФЕРЕНЦІЇ студентів
Hamza

Відповіді:


249

Якщо припустити цю таблицю:

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

Який із них ви віддаєте перевагу - питання смаку. Але ви повинні бути послідовними у своїх сценаріях. Останні два висловлювання є єдиним варіантом, якщо у вас є зовнішні ключі, на які посилається ПК, що складається з декількох стовпців - у цьому випадку ви не можете визначити FK "inline", наприкладforeign key (a,b) references foo (x,y)

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


Тип serialданих насправді не є типом даних. Це просто коротке позначення руки, яке визначає значення за замовчуванням для стовпця, взятого з послідовності. Отже, будь-який стовпець, на який посилається стовпець, визначений як serialповинен бути визначений, використовуючи відповідний базовий тип integer(або bigintдля bigserialстовпців)


Це посилання ( postgresqltutorial.com/postgresql-foreign-key ) показує інший спосіб зробити те, що ви сказали, можна зробити лише за допомогою команди «обмеження» у 3 та 4. Крім того, що робити з тим, щоб поставити FOREIGN KEY перед FK? Схоже, коли ми робимо це, нам не потрібно оголошувати тип змінної?
слова для
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.