cú pháp khóa ngoại postgresql


122

Tôi có 2 bảng như bạn sẽ thấy trong mã posgresql của tôi bên dưới. Bảng đầu tiên sinh viên có 2 cột, một cột dành cho student_name và student_id còn lại là khóa chính. Trong bảng thứ hai của tôi được gọi là các bài kiểm tra, bảng này có 4 cột, một cột cho subject_id, một cột cho tên_tối_từ, sau đó một cột cho học sinh có điểm cao nhất trong môn học là Student_id. tôi đang cố gắng làm cho highStudent_id tham chiếu đến student_id trong bảng sinh viên của tôi. Đây là mã tôi có dưới đây, tôi không chắc cú pháp có đúng không:

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

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

cú pháp có highestStudent_id SERIAL REFERENCES studentsđúng không? bởi vì tôi đã thấy một cái khác giống nhưhighestStudent_id REFERENCES students(student_id))

Xin vui lòng cho biết cách chính xác để tạo khóa ngoại trong postgresql là gì?


4
Có, cú pháp là "đúng". Tuy nhiên, cột FK không nên được định nghĩa vì serialnó phải được định nghĩa integer. serialđược không phải là một "thực" kiểu dữ liệu, đó là một tay viết tắt của Populating giá trị mặc định từ chuỗi
a_horse_with_no_name

Nếu FK tham chiếu đến khóa chính, thì không cần cột. Nếu FK tham chiếu đến một khóa thay thế, thì các cột là cần thiết.
jarlh 17/02/15

1
Khóa ngoại của bạn tham chiếu đến bảng "người chơi". Dường như bạn không bảng có tên "người chơi".
Mike Sherrill 'Cat Recall'

@Mike Sherrill 'Cat Nhớ lại xin lỗi, sai lầm của tôi, ý tôi là số nguyên cao nhấtStudent_id THAM KHẢO sinh viên
Hamza

Câu trả lời:


250

Giả sử bảng này:

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

Có bốn cách khác nhau để xác định khóa ngoại (khi xử lý một PK cột duy nhất) và chúng đều dẫn đến cùng một ràng buộc khóa ngoại:

  1. Nội tuyến mà không đề cập đến cột mục tiêu:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students
    );
  2. Nội tuyến với việc đề cập đến cột mục tiêu:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students (student_id)
    );
  3. Ngoài dòng bên trong 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. Như một alter tabletuyên bố riêng biệt :

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

Cái nào bạn thích là một vấn đề của hương vị. Nhưng bạn nên nhất quán trong các kịch bản của mình. Hai câu lệnh cuối cùng là lựa chọn duy nhất nếu bạn có các khóa ngoại tham chiếu đến một PK bao gồm nhiều hơn một cột - bạn không thể xác định FK "nội tuyến" trong trường hợp đó, ví dụ:foreign key (a,b) references foo (x,y)

Chỉ phiên bản 3) và 4) sẽ cung cấp cho bạn khả năng xác định tên riêng của bạn cho ràng buộc FK nếu bạn không thích những cái tên do hệ thống tạo ra từ Postgres.


Kiểu serialdữ liệu không thực sự là một kiểu dữ liệu. Nó chỉ là một ký hiệu tay ngắn xác định giá trị mặc định cho cột được lấy từ một chuỗi. Vì vậy, bất kỳ cột nào tham chiếu đến một cột được xác định là serialphải được xác định bằng cách sử dụng loại cơ sở thích hợp integer(hoặc bigintcho bigserialcác cột)


Liên kết này ( postgresqltutorial.com/postgresql-foreign-key ) cho thấy một cách khác để thực hiện những gì bạn đã nói chỉ có thể được thực hiện với lệnh 'ràng buộc' trong 3 và 4. Ngoài ra, còn đặt FOREIGN KEY trước FK thì sao? Có vẻ như khi chúng ta làm điều đó, chúng ta không phải khai báo kiểu biến?
wordsforthewise
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.