Mit PHP Zellen einer relationalen Verbindung auslesen

Troff

Grünschnabel
Hi Folks,

ich bin Denise, bin über Fuffzich und beschäftige mich schon eine Weile mit PHP, würde mich aber immernoch als Anfängerin bezeichnen. Nun stehe ich vor einen Problem und hoffe, eine einfache Lösung zu finden, die nicht heisst "benenne das Feld um"... ;)

Ich habe in MySQL eine relationale Datenbank gebaut. Ich habe drei Tabellen, eine beinhaltet eine Liste mit so genannten Collectoren, die haben zwar eine eindeutige ID (UUID), allerdings habe ich dennoch eine Datensatz ID hinzugefügt, um die Verknüpfung zu vereinfachen. Die zweite Tabelle beinhaltet eine Liste der über die Collectoren getätigten Zahlungen, hier ebenfalls vorhanden eine ID. Die dritte Tabelle verbindet nun in einem Datensatz die ID der Collectoren mit der ID der Zahlungen. Das klappte auch alles ganz gut, bis ich auf die Idee kam, mit die UUID, in der Tabelle "collectors" anzeigen lassen zu wollen, weil ich die gelegentlich brauche. Ich füge hier mal ein Bild der Relationen und Tabellen ein:

relationships.jpg


Das System läuft seit Jahren gut. Dass ich allerdings bei der Vergabe der Feldnamen Mist gemacht habe, fällt nun erst auf. Bei der Ausführung der Abfrage

Code:
SELECT * FROM `payments` , `collectors` , `conn_coll_pay` WHERE `collectors`.`collector_ID` != ''AND `conn_coll_pay`.`collector_ID` = `collectors`.`ID` AND `conn_coll_pay`.`payment_ID` = `payments`.`ID` ORDER BY `collectors`.`name` ASC;

kommt als Ergebnis folgendes heraus (nur Überschriften, Daten sind nicht wichtig):

--entfernt--

Wie man sehen kann, habe ich verschiedene Überschriften doppelt drin, leider auch "collector_ID". Die erste Spalte "collector_ID" beinhaltet eine UUID, die zweite Überschrift "collector_ID" stammt aus der Verbindungstabelle "conn_coll_pay" und beinhaltet die Datensatz-ID des Collectors.

Ich frage in einem PHP-Script die Datensätze zum Anzeigen einer Tabelle mittels
PHP:
$zeile = mysql_fetch_array($db_erg,MYSQL_ASSOC);
ab und hole mir dann die Inhalte der Spalten jeweils mittels
PHP:
$variable = $zeile['spaltenüberschrift'];

Soweit alles super, nur: die UUID wird nicht abgefragt, denn
PHP:
$ID=$zeile['collector_ID'];
beinhaltet den Wert aus der Spalte 'conn_coll_pay'.'collector_ID'.

Wie komme ich (hoffentlich) ohne großen Aufwand an die UUID? In MS-Access konnte man die Tabelle mit angeben, aus der man den Wert haben wollte.

Wie frage ich in PHP so etwas ab wie
PHP:
$collID = $zeile('collectors'.'collector_ID');
?

Ich habe das oben genannte schon versucht, allerdings ohne Erfolg. Wie macht man's richtig? Oder:
gibt es eine Möglichkeit, sich die Felder der Tabelle "conn_coll_pay" in der MySQL-Abfrage ausblenden zu lassen?

Danke im Voraus,

Denise
 
Zuletzt bearbeitet von einem Moderator:
Hi,

wenn ich dich richtig verstehe, dann hast du im Moment das Problem, dass du durch das mysql_fetch_assoc() gewisse Spalten nicht abrufen kannst ,weil diese sich gegenseitig überschreiben, oder?
Als einfachste Lösung könntest du deine SQL Abfrage mit Aliasen definieren:
SQL:
SELECT p.ID as payment_id, p.`date` AS payment_date, .....

Ist zwar etwas Fleissarbeit, aber somit hätte jede Spalte einen eindeutigen Namen.

Off-Topic:
- Ein "SELECT *" ist übrigens nicht schön, hier werden fast immer Daten vom Server geholt, welche danach nicht benötigt werden. Dies wirkt sich negativ auf die Performance aus und kann zu eben jenem Problem führen, welches du gerade hast.
- Der Spaltenname "date" ist unschön, "date" ist ein Schlüsselwort von SQL.
- Die mysql_* Funktionen sind schon seit Jahren deprecated (veraltet) und wurden mit PHP 7 entfernt. Ein paar Gründe hierfür stehen zum Beispiel hier oder hier (mit Erklärungen zum Umstieg auf andere Möglichkeiten). Bitte steige eintweder auf die mysqli Erweiterung oder PDO um, sonst kann es sein dass die Seite nach einem Update des Servers nicht mehr läuft.

Grüsse,
BK
 
Zuletzt bearbeitet:
Die Namensgebung ist richtig. Gleiches soll auch gleich benannt werden.
Ganz einfach gesagt. Dein Problem ist der *.
Lassen wir mal alles PHP weg und konzentrieren uns auf das SQL.
SQL:
SELECT * FROM payments , collectors , conn_coll_pay ...
Das bedeutet, nimm alle Felder aus allen 3 Tabellen. Und zag, du hast Feldnamen doppelt drin. Darum sollte man immer auf * verzichten.
Du kannst die Felder zur Ausgabe ansteuern. ggf sogar den Namen überschreiben.

Zur besseren Lesbarkeit empfiehlt es sich, die Tabellennamen mit einem Alias abzukürzen. Achtung. Im Where-bereich muss dann der Alias verwendet werden
SQL:
SELECT
    *
FROM
    payments pay,
    collectors col,
    conn_coll_pay con
WHERE
    col.collector_ID != ''
    AND con.collector_ID = col.ID
    AND con.payment_ID = pay.ID
ORDER BY
    col.name ASC;
Damit ist das Problem noch nicht gelöst.
Jetzt ersetzen wird den * durch alle Felder wie wirklich gebraucht werden
SQL:
SELECT
    col.collection_id,
    -- Ein Beispiel mit alias
    col.id AS col_internal_id,
    com.name
    -- etc. nur die Felder auflisten, die nachher gebraucht werden
FROM
    payments pay,
    collectors col,
    conn_coll_pay con
WHERE
    col.collector_ID != ''
    AND con.collector_ID = col.ID
    AND con.payment_ID = pay.ID
ORDER BY
    col.name ASC;

Nebenbei. Zum Thema Lesbarkeit von SQL-Strings innerhalb von PHP empfehle ich die folgende Lektüre: PHP: SQL-Statement in PHP lesbar darstellen
 
Hallo Bratkartoffel, Hallo Yaslaw,

kannte ich nicht diese Möglichkeit. Aber werde ich sofort umsetzen und dann wird es auch funktionieren. Vielen Dank für den Tip, ich berichte nach!

@Bratkartoffel: Du hast natürlich vollkommen recht mit den deprecated Befehlen. Gut nur, dass ich so schnell nicht damit rechnen muss, dass mir die Scripte nicht mehr laufen werden, weil (seehr doof nur) mein Serverprovider diese neuesten Updates nicht zur Verfügung stellt. Aber Danke für den Tip, ich werde das gleich mit umbauen, dann habe ich nicht den Hickhack, wenn ich per Hand meinen Server update.

@Yaslaw: Danke für den Tip mit der besseren Schreibweise in PHP. Ich habe es ähnlich übersichtlich aufgebaut. War schon deshalb nötig, weil ich meine SQL-Abfragen dynamisch zusammensetze. Ich hätte sonst komplett den Überblick verloren. Mit komplexen Dingen, haben wir Frauen das ja nicht sooo... ;-)
 
Zu den mysql_*. Egal was der Provider anbietet. Mach es jetzt, wo du den Code bereits am Bearbeiten bist.
Ist wie beim Auto: "Winterreifen brauche ich nicht, Es hat ja schon lange keinen wirklichen Winter mehr gegeben". Und wenn er dann plötzlich kommt, hat man verloren.

zudem, wenn dein Provider keine Updates macht, würde ich wechseln. Das ist ein Sicherheitsrisiko.
 
So, nachdem ich nun die benötigten Felder händisch eingefügt habe, funktioniert auch die Ausgabe wie gewünscht. Vielen Dank an Yaslaw und Bratkartoffel! Ich werde das Thema als gelöst markieren und mich dann daran machen, die 56 Scripte händisch auf mysqli umzutickern... :-O Dazu erstmal alles auf eine neue Testumgebung verschieben... ;-)
 
Zurück