Fremdschlüssel oder INNER JOIN für normierte DB

  • Hallo,
    die Thematik mit den Fremdschlüsseln in MYSQL habe ich noch nicht so ganz verstanden.
    Und zwar habe ich die folge Tabelle angelegt:
    [Blockierte Grafik: http://fs5.directupload.net/images/160609/lhk7gmqw.jpg]
    Diese möchte ich jetzt normieren.
    Dazu muss ich doch nur die Spalte pic_cat in eine extra Tabelle auslagern oder?
    Wenn ich das auslager, muss ich ja irgenwie mit einem Fremdschlüssel auf diese Tabelle verweisen.
    Da ich kein INNODB in PHPmyAdmin einstellen kann, kann ich ja scheinbar keine Fremdschlüssel direkt definieren.
    Daher habe ich 2 Ansätze im Internet gefunden. Einmal über Foreign Key's und mit dem JOIN befehl.
    Was genau ist da der Unterschied zwischen den beiden Methoden?


    Gruß
    Torben

  • Der Unterschied zw. Foreign keys und Fremdschlüssel ist ... die Sprache :D
    Foreign key (in db meist fk abgekürzt) ist englisch für Fremdschlüssel.


    Wenn Du eine Tabelle normalisieren möchtest, dann kann man Fremdschlüssel (fk) verwenden.
    Muss aber nicht. (Ich würde es aber empfehlen)
    (BTW: http://www.php-kurs.com/normalisierung.htm)


    Im Bsp Deiner Tabelle (was ist pic_cat und warum muss es raus/in einer andere Tabelle?)
    würdest du eine neue Tabelle anlegen:


    Code
    1. |pic_cat_id |pic_cat
    2. +-----------+---------------
    3. |1 |...
    4. |2 |...


    Es empfiehlt sich `pic_cat_id` statt `id`.


    In Deiner Haupttabelle änderst Du pic_cat in einen Fremdschlüssel:



    Wenn Du nun ein (was auch immer das ist) neues pic_cat einfügen willst,
    dann machst Du das in der neuen Nebentabelle (hier im Bsp `my_new_tbl`).
    Die bekommt automatisch eine increment id (zb 5).
    In der Haupttabelle nutzt Du nun nur noch die `pic_cat_id` aus der Nebentabelle.
    Bsp:

    Code
    1. |bildID |pfad |title |pic_cat_id ...
    2. +-------+-------+-------+----------- ...
    3. |1 |... |... |5
    4. |2 |... |... |5
    5. |3 |... |... |111


    Die ersten beiden Rows in der Haupttabelle nutzen beide die `pic_cat_id` 5
    welche als fk fungiert
    und auf die Row mit der `pic_cat_id` 5 in der neuen Nebentabelle zeigen.


    Die beiden Tabelle stehen nun direkt in Beziehung miteinander.
    Durch update CASCADE stellst Du sicher,
    dass das Ändern der `pic_cat_id` der neuen Tabelle
    auf die Haupttabelle übernommen wird.


    Info: das alles geht auch ohne fk. Musst Du die beiden Tabellen "überwachen".


    Für weiteres/genaueres fragen oder: http://dev.mysql.com/doc/refma…e-table-foreign-keys.html

  • Danke für die gute und ausführliche Erklärung.


    pic_cat ist die Kategorie des Bildes. also zum beispiel folgendes:

    HTML
    1. |pic_cat_id |pic_cat
    2. +---------------------+---------------
    3. |1 | Landschaftsbilder
    4. |2 | Architekturfotos
    5. |3 | ....


    Ich wollte aber eigentlich nicht den Unterschied zwischen . Foreign keys und Fremdschlüsseln wissen, sondern den Unterschied zwischen Fremdschlüsseln und JOIN's

  • Dann macht das auch Sinn =)


    Fremdschlüssel wie oben beschrieben.
    JOIN nutzt man, um eine oder mehrere Tabellen in die Query einzubinden.
    Kann man also nicht vergleichen.


    Bsp:

    SQL
    1. SELECT ...
    2. FROM `main_table` AS `main`
    3. JOIN `pic_cat_tbl` AS `cat` ON (`main`.`pic_cat_id` = `cat`.`pic_cat_id`)
    4. WHERE


    oder

    SQL
    1. SELECT ...
    2. FROM `main_table` AS `main`
    3. LEFT JOIN `pic_cat_tbl` AS `cat` USING (`pic_cat_id`)
    4. WHERE
    5. `main`.`sometihng` = 'someting'
    6. AND `cat`.`pic_cat_something` = 'seomthing'


  • Ich habe das jetzt mal probiert auf eine andere Tabelle anzuwenden. leider kommt immer eine Fehlermeldung:

    Zitat

    #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''bilder' ADD CONSTRAINT 'fk_user-id' FOREIGN KEY ('user-id') REF' at line 1


    SQL
    1. ALTER TABLE 'bilder'
    2. ALTER TABLE 'bilder'
    3. ADD CONSTRAINT 'fk_user-id'
    4. FOREIGN KEY ('user-id')
    5. REFERENCES 'users' ('id')
    6. ON UPDATE CASCADE
    7. ON DELETE CASCADE


    Kurz zu meiner Struktur:
    die Tabelle users hat den Primärschlüssel id.
    Dieser soll als Fremdschlüssel in der Tabelle bilder stehen.
    darum habe ich in dieser Tabelle die Spalte user-id als int feld angelegt.
    Aber sql code funktioniert nicht. Was mache ich jetzt schon wieder falsch? :(
    Die Spalte id in der Tabelle users würde ich ungerne bearbeiten, auch wenn sie blöd benannt wurde. Denn darauf bauen viele Php skripte auf und ich möchte ungerne alle dateien danach absuchen...

  • Alles richtig - außer die Anführungsstriche =)


    'bilder' -- die einfachen Anführungsstriche sind der Fehler.
    Das sind keine Value-Felder, sondern Schlüssel/Keys - daher hier: `
    also

    Code
    1. `bilder` statt 'bilder'

    .
    Auch bei allen anderen Keys wie zB fk_user-id ect.
    (ALTER TABLE 'bilder' kommt auch 2 mal vor, aber das war sicherlich ein Kopierfehler)



    Empfehlung: keine Bindestriche im Code nutzen.
    Off möchte man einen Key kopieren, um Schreibfehler zu vermeiden.
    Bei diesem_key reicht ein Doppelklick zum markieren. Bei diesem-key musst Du mit der Maus rum eiern.



    Note: durch ON DELETE CASCADE wird beim Löschen der Referenz (also des Users) auch die betreffenden Rows in `bilder` gelöscht.
    Wenn das so sein soll - OK.
    Um Bilder nicht zu verlieren, könntest Du auch ON DELETE SET NULL wählen.
    Ein Fremdschlüsselfeld muss immer ein Gegenstück in der Referenztabelle besitzen,
    oder NULL sein (also entweder fk existiert, oder das feld ist null).