Προς το περιεχόμενο

SQL script -- Πού είναι το κακό να έχω δυο ξένα κλειδιά;


nikolaos_

Προτεινόμενες αναρτήσεις

Δημοσ.

Γράφω στον text editor το εξής sql σκριπτάκι:

 

>
create database ERGASIA;
use ERGASIA;
create table LIMANI
   (
   ONOMASIA VARCHAR(20), primary key (ONOMASIA),
   XORHTIKOTHTA INTEGER
   ) ENGINE=INNODB;
create table PELATHS
   (
   ARITHMOS_TAYTOTHTAS CHAR(10), primary key (ARITHMOS_TAYTOTHTAS),
   ONOMATEPONYMO VARCHAR(45),
   AFETHRIA VARCHAR(20) NOT NULL,
   PROORISMOS VARCHAR(20) NOT NULL,
   THLEFONO CHAR(15),
   EPITHYMHTH_HMEROMHNIA_ANAXORHSHS DATE,
   OFEILH NUMERIC(6,2),
   foreign key (AFETHRIA) references LIMANI(ONOMASIA) ON DELETE SET NULL ON UPDATE CASCADE,
   foreign key (PROORISMOS) references LIMANI(ONOMASIA) ON DELETE SET NULL ON UPDATE CASCADE
   ) ENGINE=INNODB;

 

και παίρνω απάντηση:

 

>
ERROR 1005 (HY000): Can't create table 'ERGASIA.PELATHS' (errno: 150)

 

Τι φταίει; Τα δυο ξένα κλειδιά που βλέπουν στον ίδιο πίνακα; Έκανα κανένα συντακτικό λάθος; Πώς το θέλει για να το δεχτεί;

Δημοσ.

Μα ο σκοπός του foreign key είναι να αναφέρεται σε ένα primary key σε ένα άλλο table, με πια λογική πας να φτιάξεις ένα foreign key που αναφέρεται σε μεταβλητή του ίδιου πίνακα;

 

edit: μαλακια είπα δεν διάβασα καλά τι γραφεις , καταραμένη δυσλεξία. Θα το ξανατσεκαρο τώρα που είδα τι γραφής και θα σου απαντήσω άμα βρω κάτι

Δημοσ.

Το πρόβλημα είναι ότι ορίζεις το πεδίο AFETHRIA να μην είναι NULL αλλά στον ορισμό του foreign key ορίζεις ON DELETE SET NULL. Δεν γίνεται να του λες να κάνει NULL ένα πεδίο που είναι NOT NULL.

Δημοσ.

Αυτό που μπορείς να κάνεις είναι να έχεις μία κολόνα foreign key π.χ. LIMANI_ID αντί για AFETHRIA & PROORISMOS .Επίσης να προσθέσεις στον πίνακα PELATHS άλλη μία κολόνα TYPOS_LIMANIOY που να παίρνει τιμές ΑΦΕΤΗΡΙΑ και ΠΡΟΟΡΙΣΜΟΣ. Άρα μπορείς να έχεις 2 εγγραφές στον πίνακα PELATHS που θα αναφέρονται στον ίδιο πελάτη και η μία θα αναφέρεται στον προορισμό και η άλλη στην αφετηρία.

Δημοσ.
Το πρόβλημα είναι ότι ορίζεις το πεδίο AFETHRIA να μην είναι NULL αλλά στον ορισμό του foreign key ορίζεις ON DELETE SET NULL. Δεν γίνεται να του λες να κάνει NULL ένα πεδίο που είναι NOT NULL.

 

Τέσταρα το script σου, και ισχύει αυτό που λέει ο Τάσος, δεν βγάζει άλλο error. Γενικά όμως σαν λογική να ορίζεις ονομασία ενός λιμανιού σαν primary key είναι λανθασμένη, γιατί το primary key έχει την εννιά του μοναδικού. Για παράδειγμα άμα μιλάμε για τα λιμάνια όλου του κόσμου μπορεί αν υπάρξουν πάνω από ένα λιμάνια με το ίδιο όνομα, οπότε αυτό είναι πρόβλημα, για αυτό σαν primary keys το πιο συνηθισμένο είναι αν χρησιμοποιούμε ids.

Δημοσ.
Το πρόβλημα είναι ότι ορίζεις το πεδίο AFETHRIA να μην είναι NULL αλλά στον ορισμό του foreign key ορίζεις ON DELETE SET NULL. Δεν γίνεται να του λες να κάνει NULL ένα πεδίο που είναι NOT NULL.

 

Είχες δίκιο, αυτό ήταν η γκάφα. Άλλαξα το SET NULL σε RESTRICT και το πήρε.

Είχα κι άλλους πίνακες για τη βάση κι όλοι με τον ίδιο τρόπο διορθώθηκαν.

 

Πάντως, σε μια προηγούμενη φάση, δεν είχα γράψει ούτε τα NOT NULL στα μεγέθη που θα γίνονταν primary keys, ούτε το ON DELETE μετά τον ορισμό των foreign keys. Και υποθέτωντας ότι θα τα καταλάβει από default, πάλι είχε αποτύχει.

 

Όντως ξέρω ότι προτιμώνται άλλοι τύποι δεδομένων για primary keys, αλλά αυτή τη στιγμή η βάση δεν θα πάρει παραπάνω από 100 στοιχεία. Είχα την εντύπωση ότι "δεν επιτρέπονταν δυο ξένα κλειδιά στον ίδιο πίνακα" και θα μου ήταν έκπληξη.

 

Ευχαριστώ πολύ!

Επισκέπτης
Δημοσ.

σε κάθε περίπτωση, το σχήμα της βάσης σου είναι λάθος...

δεν ξέρω ακριβώς τι θέλεις να πετύχεις, αλλά φαντάζομαι στην πορεία θα χρειαστείς πίνακες για τις οντότητες

ΛΙΜΑΝΗ, ΠΕΛΑΤΗΣ, ΔΡΟΜΟΛΟΓΙΟ και ΤΑΞΙΔΙ τα οποία θα συνδέονται με ξένα κλειδιά πάνω στα primary keys τους...οποιαδήποτε άλλη σύνδεση, ναι μεν μπορεί να δουλεύει, δεν θα είναι ωστόσο η σωστή προσέγγιση...

Δημοσ.

Νομιζω οτι θα το εκτιμησει ο καθηγητης αν του δειξεις οτι αποκτας καλες συνηθειες και δεν κανεις το ονομα του λιμανιου primary key αλλα βαλεις καποιον αυξοντα αριθμο. Γενικα σε ολους τους πινακες σου

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...