60

Ho 2 tabelle come vedrete nel mio codice posgresql di seguito. Gli studenti della prima tabella hanno 2 colonne, una per student_name e l'altra student_id che è la chiave primaria. Nella mia seconda tabella chiamata test, questo ha 4 colonne, una per subject_id, una per il subject_name, quindi una per uno studente con il punteggio più alto in un soggetto che è highestStudent_id. Sto cercando di rendere highestStudent_id riferirsi a student_id nella mia tabella studenti. Questo è il codice che ho seguito, non so se la sintassi è corretta:sintassi di chiave esterna postgresql

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

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

è la sintassi corretta highestStudent_id SERIAL REFERENCES students? perché ne ho visto un altro come highestStudent_id REFERENCES students(student_id))

Quale sarebbe il modo corretto di creare la chiave esterna in postgresql per favore?

+4

Sì la sintassi è "corretta". Tuttavia la colonna FK dovrebbe ** non ** essere definita come 'seriale', dovrebbe essere definita come' intero '. 'serial' non è un tipo di dati" reale ", è una mano breve per popolare il valore predefinito dalla sequenza –

+0

Se l'FK fa riferimento a una chiave primaria, non sono necessarie colonne. Se l'FK fa riferimento a una chiave alternativa, sono necessarie le colonne. – jarlh

+0

@a_horse_with_no_name intendi in questo modo: highestStudent_id numero intero REFERENCES player – Hamza

risposta

118

Assumendo questa tabella:

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

Ci sono quattro modi diversi per definire una chiave esterna (quando si tratta di un singolo PK colonna) e tutti portano allo stesso vincolo di chiave esterna:

  1. linea senza menzionare la colonna di destinazione:

    CREATE TABLE tests 
    ( 
        subject_id SERIAL, 
        subject_name text, 
        highestStudent_id integer REFERENCES students 
    ); 
    
  2. I nline con menzionare la colonna di destinazione:

    CREATE TABLE tests 
    ( 
        subject_id SERIAL, 
        subject_name text, 
        highestStudent_id integer REFERENCES students (student_id) 
    ); 
    
  3. fuori linea all'interno del 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. Come alter table dichiarazione separata:

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

quale preferite è una questione di gusti. Ma dovresti essere coerente nei tuoi script. Le ultime due istruzioni sono l'unica opzione se si dispone di chiavi esterne che fanno riferimento a un PK costituito da più di una colonna: in tal caso, non è possibile definire l'FK "in linea", ad es. foreign key (a,b) references foo (x,y)

Solo le versioni 3) e 4) ti daranno la possibilità di definire il tuo nome per il vincolo FK se non ti piacciono i sistemi generati da Postgres.


Il tipo di dati serial non è in realtà un tipo di dati. È solo una notazione a mano corta che definisce un valore predefinito per la colonna presa da una sequenza. Quindi qualsiasi colonna riferimento una colonna definita come serial deve essere definito utilizzando il tipo appropriato di base integer (o bigint per bigserial colonne)

+0

grazie per tale spiegazione dettagliata. Apprezzo molto e ora sono chiaro su come creare riferimenti tra i miei tavoli e utilizzare i giusti tipi di base. grazie @a_horse_with_no_name – Hamza

+7

Per il tuo secondo esempio dovrebbe essere 'highestStudent_id intero REFERENCES studenti (student_id)' invece di 'highestStudent_id intero REFERENCES studenti (id)'? O è id? Una sorta di stenografia? – John