postgresql ไวยากรณ์คีย์ต่างประเทศ


122

ฉันมี 2 ตารางดังที่คุณจะเห็นในรหัส posgresql ด้านล่าง นักเรียนในตารางแรกมี 2 คอลัมน์คอลัมน์หนึ่งสำหรับ student_name และ student_id อื่น ๆ ซึ่งเป็นคีย์หลัก ในตารางที่สองของฉันเรียกว่าการทดสอบมี 4 คอลัมน์คอลัมน์หนึ่งสำหรับ subject_id หนึ่งคอลัมน์สำหรับชื่อเรื่องและอีกคอลัมน์สำหรับนักเรียนที่มีคะแนนสูงสุดในวิชาที่สูงที่สุดนักเรียน_id ฉันกำลังพยายามทำให้ maximumStudent_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))

อะไรคือวิธีที่ถูกต้องในการสร้าง Foreign Key ใน postgresql?


4
ใช่ไวยากรณ์นั้น "ถูกต้อง" อย่างไรก็ตามคอลัมน์ FK ควรไม่ได้ถูกกำหนดเป็นก็ควรกำหนดให้เป็นserial ไม่ใช่ประเภทข้อมูล "จริง" เป็นคำสั่งสั้น ๆ สำหรับการเติมค่าเริ่มต้นจากลำดับintegerserial
a_horse_with_no_name

หาก FK อ้างอิงคีย์หลักไม่จำเป็นต้องมีคอลัมน์ หาก FK อ้างอิงคีย์สำรองจำเป็นต้องมีคอลัมน์
jarlh

1
คีย์ต่างประเทศของคุณอ้างอิงตาราง "ผู้เล่น" คุณไม่ปรากฏว่ามีตารางชื่อ "ผู้เล่น"
Mike Sherrill 'Cat Recall'

@ Mike Sherrill 'Cat Recall ขอโทษความผิดพลาดของฉันฉันหมายถึงนักเรียนที่อ้างอิงจำนวนเต็มสูงสุด Student_id
Hamza

คำตอบ:


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คอลัมน์)


ลิงค์นี้ ( postgresqltutorial.com/postgresql-foreign-key ) แสดงอีกวิธีหนึ่งในการทำสิ่งที่คุณกล่าวว่าสามารถทำได้ด้วยคำสั่ง 'ข้อ จำกัด ' ใน 3 และ 4 เท่านั้นนอกจากนี้การใส่คีย์ต่างประเทศก่อน FK ล่ะ ดูเหมือนว่าเมื่อเราทำเช่นนั้นเราไม่จำเป็นต้องประกาศประเภทตัวแปร?
wordsforthewise
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.