Składnia klucza obcego postgresql

122

Mam 2 tabele, jak zobaczysz w moim kodzie posgresql poniżej. Pierwsza tabela uczniów ma dwie kolumny, jedną dla ucznia_nazwa, a drugą student_id, który jest kluczem podstawowym. W mojej drugiej tabeli o nazwie testy, zawiera ona 4 kolumny, jedną dla subject_id, jedną dla subject_name, a następnie jedną dla ucznia z najwyższym wynikiem z przedmiotu, który jest najwyższymStudent_id. próbuję, aby parametr najwyższyStudent_id odnosił się do student_id w tabeli moich uczniów. Oto kod, który mam poniżej, nie jestem pewien, czy składnia jest poprawna:

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

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

czy składnia jest highestStudent_id SERIAL REFERENCES studentspoprawna? ponieważ widziałem inny podobnyhighestStudent_id REFERENCES students(student_id))

Jaki byłby poprawny sposób tworzenia klucza obcego w postgresql?

Hamza
źródło
4
Tak, składnia jest „poprawna”. Jednak kolumna FK nie powinna być definiowana tak serial, jak powinna integer. serialnie jest „prawdziwym” typem danych, to krótka ręka do
zapełnienia
Jeśli FK odwołuje się do klucza podstawowego, nie są potrzebne żadne kolumny. Jeśli FK odwołuje się do klucza alternatywnego, potrzebne są kolumny.
jarlh
1
Twój klucz obcy odwołuje się do tabeli „graczy”. Wygląda na to, że nie masz stołu o nazwie „gracze”.
Mike Sherrill „Cat Recall”
@Mike Sherrill 'Cat Recall, przepraszam, mój błąd chodziło mi o najwyższąStudent_id integer REFERENCES studenci
Hamza

Odpowiedzi:

251

Zakładając tę ​​tabelę:

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

Istnieją cztery różne sposoby definiowania klucza obcego (w przypadku pojedynczej kolumny PK) i wszystkie prowadzą do tego samego ograniczenia klucza obcego:

  1. W tekście bez wzmianki o kolumnie docelowej:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students
    );
  2. W wierszu ze wzmianką o kolumnie docelowej:

    CREATE TABLE tests 
    ( 
       subject_id SERIAL,
       subject_name text,
       highestStudent_id integer REFERENCES students (student_id)
    );
  3. Poza linią wewnątrz 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. Jako osobne alter tableoświadczenie:

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

Który wolisz, to kwestia gustu. Ale powinieneś być konsekwentny w swoich skryptach. Ostatnie dwie instrukcje są jedyną opcją, jeśli masz klucze obce odwołujące się do PK, który składa się z więcej niż jednej kolumny - nie możesz w takim przypadku zdefiniować „inline” FK, np.foreign key (a,b) references foo (x,y)

Tylko wersja 3) i 4) daje możliwość zdefiniowania własnej nazwy dla ograniczenia FK, jeśli nie podoba ci się te wygenerowane przez system z Postgres.


Typ serialdanych tak naprawdę nie jest typem danych. Jest to po prostu krótka notacja ręczna, która definiuje domyślną wartość kolumny pobraną z sekwencji. Zatem każda kolumna odwołująca się do kolumny zdefiniowanej jako serialmusi być zdefiniowana przy użyciu odpowiedniego typu podstawowego integer(lub bigintdla bigserialkolumn)

koń bez imienia
źródło
Ten link ( postgresqltutorial.com/postgresql-foreign-key ) pokazuje inny sposób zrobienia tego, co powiedziałeś, można zrobić tylko za pomocą polecenia „constraint” w 3 i 4. Ponadto, co z umieszczeniem KLUCZA OBCEGO przed FK? Wygląda na to, że kiedy to robimy, nie musimy deklarować typu zmiennej?
słowa z