sintaks kunci asing postgresql

122

Saya memiliki 2 tabel seperti yang akan Anda lihat di kode posgresql saya di bawah ini. Siswa tabel pertama memiliki 2 kolom, satu untuk student_name dan student_id lainnya yang merupakan primary key. Dalam tabel kedua saya yang disebut tes, ini memiliki 4 kolom, satu untuk subject_id, satu untuk subject_name, kemudian satu untuk siswa dengan skor tertinggi dalam subjek yang merupakan nilai_tertinggi. Saya mencoba membuat latestStudent_id merujuk ke student_id di tabel siswa saya. Ini adalah kode yang saya miliki di bawah ini, saya tidak yakin apakah sintaksnya benar:

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

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

apakah sintaksnya highestStudent_id SERIAL REFERENCES studentsbenar? karena saya telah melihat yang lain sepertihighestStudent_id REFERENCES students(student_id))

Apa cara yang benar untuk membuat kunci asing di postgresql?

Hamza
sumber
4
Ya, sintaksnya "benar". Namun kolom FK tidak harus didefinisikan sebagaimana serialmestinya integer. serialbukan tipe data "nyata", ini adalah cara singkat untuk mengisi nilai default dari urutan
a_horse_with_no_name
Jika FK mereferensikan kunci utama, tidak ada kolom yang diperlukan. Jika FK mereferensikan kunci alternatif, kolom diperlukan.
jarlh
1
Kunci asing Anda merujuk pada tabel "pemain". Anda tampaknya tidak memiliki tabel bernama "pemain".
Mike Sherrill 'Cat Recall'
@Mike Sherrill 'Cat Recall maaf, kesalahan saya maksud saya integer tertinggiStudent_id REFERENSI siswa
Hamza

Jawaban:

250

Dengan asumsi tabel ini:

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

Ada empat cara berbeda untuk mendefinisikan kunci asing (saat menangani satu kolom PK) dan semuanya mengarah ke batasan kunci asing yang sama:

  1. Sebaris tanpa menyebutkan kolom target:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students
    );
  2. Sejalan dengan menyebutkan kolom target:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students (student_id)
    );
  3. Keluar dari baris di dalam 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. Sebagai alter tablepernyataan terpisah :

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

Yang mana yang Anda sukai adalah soal selera. Tetapi Anda harus konsisten dalam skrip Anda. Dua pernyataan terakhir adalah satu-satunya pilihan jika Anda memiliki kunci asing yang mereferensikan PK yang terdiri dari lebih dari satu kolom - Anda tidak dapat mendefinisikan FK "sebaris" dalam kasus itu, misalnyaforeign key (a,b) references foo (x,y)

Hanya versi 3) dan 4) yang akan memberi Anda kemampuan untuk menentukan nama Anda sendiri untuk batasan FK jika Anda tidak menyukai sistem yang dihasilkan dari Postgres.


The serialtipe data tidak benar-benar tipe data. Itu hanya notasi tangan pendek yang mendefinisikan nilai default untuk kolom yang diambil dari sebuah urutan. Jadi setiap kolom yang mereferensikan kolom yang ditentukan serialharus ditentukan menggunakan tipe dasar yang sesuai integer(atau bigintuntuk bigserialkolom)

seekor kuda tanpa nama
sumber
Tautan ini ( postgresqltutorial.com/postgresql-foreign-key ) menunjukkan cara lain untuk melakukan apa yang Anda katakan hanya dapat dilakukan dengan perintah 'kendala' di 3 dan 4. Juga, bagaimana dengan meletakkan KUNCI ASING sebelum FK? Sepertinya ketika kita melakukan itu, kita tidak perlu mendeklarasikan tipe variabel?
demikian juga