• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Formulardaten an mehrere Tabellen übergeben

Tronjer

Senior HTML'ler
Ich habe hier ein HTML-Formular, dessen Eingaben nicht in eine, sondern in zwei Tabellen derselben Datenbank geschrieben werden sollen. Mein erster Ansatz war, die SQL queries hintereinander zu reihen und in einer Variablen zu speichern.
PHP:
function lege_produkt_an ($db)
{
    if ($_POST) {
        $produkt = array(
        ':artikel_gruppe'        => $_POST['artikel_gruppe'],
        ':artikel_name'          => ucfirst($_POST['artikel_name']),
        ':artikel_ausfuehrung'   => $_POST['artikel_ausfuehrung'],
        ':artikel_detail'        => ucfirst($_POST['artikel_detail']),
        ':artikel_auflage'       => $_POST['artikel_auflage'],
        ':artikel_preis'         => $_POST['artikel_preis']
        );
        $abfrage = 'INSERT INTO produkte (artikel_gruppe, artikel_name, artikel_ausfuehrung, ' .
                   'artikel_detail) VALUES (:artikel_gruppe, :artikel_name, :artikel_ausfuehrung, ' .
                   ':artikel_detail)';
                   'INSERT INTO preise (artikel_gruppe, artikel_auflage, artikel_preis) ' .
                   'VALUES (:artikel_gruppe, :artikel_auflage, :artikel_preis)';
        $abfrage = $db->prepare($sql);
        $abfrage->execute($produkt);
    } else {
        echo 'Fehler beim Eintrag in die Datenbank';
    }
    return $abfrage;
}

Das produziert leider eine Fehlermeldung: 'PDOException' with message 'SQLSTATE[HY000]: General error: 1065 Query was empty' .

Wie macht man denn so etwas? Aufsplittung in zwei Abfragen, mit zwei Arrays und if (wenn das erste query erfolgreich war, dann führe das zweite aus)? Ich brauche als Ergebnis einen Rückgabewert.
 
Werbung:
Werbung:
Das hier…

PHP:
        $abfrage = 'INSERT INTO produkte (artikel_gruppe, artikel_name, artikel_ausfuehrung, ' .
                   'artikel_detail) VALUES (:artikel_gruppe, :artikel_name, :artikel_ausfuehrung, ' .
                   ':artikel_detail)';

                   'INSERT INTO preise (artikel_gruppe, artikel_auflage, artikel_preis) ' .
                   'VALUES (:artikel_gruppe, :artikel_auflage, :artikel_preis)';

…ist syntaktisch erst mal Unsinn. (Leerzeile eingefügt, um es offensichtlicher zu machen. Du meinst hier außerdem $sql =, nicht $abfrage =.)

Das müsstest du aber in zwei einzelne Queries aufspalten, ja. Vermutlich bietet sich der Einsatz einer Transaktion an, um sicherzustellen, dass entweder beide INSERT-Queries ausgeführt werden oder gar keine.

- PHP: Transactions and auto-commit - Manual
 
So, ich habe die Funktion mal umgeschrieben und sie funktioniert sogar. Wollte mich aber vergewissern, ob das so wirklich korrekt und sauber ist. Die Einträge für artikel_gruppe und waren_gruppe sind in beiden Tabellen vorhanden und deswegen musste ich die Parameter auch doppelt binden. Weil ansonsten die Fehlermeldung number of bound variables does not match ... kam.

Ließe sich bindParam() eigentlich auch als assoziatives Array schreiben? Das sieht alles so redundant aus. :sad:

PHP:
function lege_produkt_an ($db)
{
    if ($_POST) {
        $db->beginTransaction();
        // Erster Query
        $sql_1 = 'INSERT INTO produkte (artikel_gruppe, artikel_name, artikel_ausfuehrung, ' .
                 'artikel_detail) VALUES (:artikel_gruppe, :artikel_name, :artikel_ausfuehrung, ' .
                 ':artikel_detail)';
        $produkteintrag = $db->prepare($sql_1); 
        $produkteintrag->bindParam(':artikel_gruppe', $_POST['artikel_gruppe']);
        $produkteintrag->bindParam(':artikel_name', $_POST['artikel_name']);
        $produkteintrag->bindParam(':artikel_ausfuehrung', $_POST['artikel_ausfuehrung']);
        $produkteintrag->bindParam(':artikel_detail', $_POST['artikel_detail']);
        $produkteintrag->execute(); 
        // Zweiter Query
        $sql_2 = 'INSERT INTO preise (artikel_gruppe, artikel_name, artikel_auflage, artikel_preis) ' .
                   'VALUES (:artikel_gruppe, :artikel_name, :artikel_auflage, :artikel_preis)';
        $preiseintrag = $db->prepare($sql_2); 
        $preiseintrag->bindParam(':artikel_gruppe', $_POST['artikel_gruppe']);
        $preiseintrag->bindParam(':artikel_name', $_POST['artikel_name']);
        $preiseintrag->bindParam(':artikel_auflage', $_POST['artikel_auflage']);
        $preiseintrag->bindParam(':artikel_preis', $_POST['artikel_preis']);
        $preiseintrag->execute();
        $db->rollBack();
    }
}
 
Zuletzt bearbeitet:
Werbung:
Lässt sich aber leider nicht anders machen. Zumindest die Artikelgruppe benötige ich als Foreign Key und da es für jeden Artikel unterschiedliche Druckauflagen gibt, kann sie auch nicht Unique sein.
 
Ich kann auch nur empfehlen, dich da ein wenig einzulesen, Tronjer. Bei einer „seltsamen“ Datenstruktur machst du dir das Leben unter Umständen später ganz schön schwer, weil Joins nicht durchführbar sind oder so.
 
Werbung:
Wieso seltsame Datenstruktur? Jeder Artikel kann in unterschiedlichen Ausführungen und Auflagen vorhanden sein (bsw. Warengruppe 2, Postkarten, einseitig bedruckt, Auflage 100, 200, 500, 1000 St., Warengruppe 3, Postkarten, zweiseitig bedruckt, Auflage 100, 200, 500, 1000 St.). Wenn ich nun alle Postkarten auslesen will, so kann ich entweder nach Warengruppe oder Artikel suchen. Die Kategorie wird in der der Navigation verlinkt und damit sieht mein Query für die Ausgabe der Produktseiten dann so aus:
PHP:
('SELECT produkte.artikel_name, produkte.artikel_detail, produkte.artikel_ausfuehrung, produkte.artikel_ausfuehrung, produkte.artikel_format, ' .
'preise.artikel_auflage, preise.artikel_preis FROM produkte JOIN preise ON produkte.artikel_gruppe = preise.artikel_gruppe WHERE preise.artikel_name = "' . $_GET['kategorie'] . '"');

Ich könnte das auch alles in eine Tabelle schreiben, LIKE verwenden, oder, was sicherlich eleganter wäre, Klassen und ORM einsetzen. Andererseits ist das ein reines Übungsprojekt, das erste Mal, dass ich eine Abfrage über mehrere Tabellen vornehme, und obendrein meine erste PHP-Site, welche ich komplett erstellen und anschließend auf dem Server deployen will. Sozusagen ein Testlauf.

Wenn hier logische Fehler vorhanden sind, oder ich Spaghetti-Code schreibe, dann sage es ruhig. Aus Fehlern lernt man ja bekanntlich.
 
Es geht doch vermutlich noch um diese Preisliste? (http://www.html.de/datenbanken-z-b-mysql/40768-preisliste.html)

In #5 gibst Du die beiden folgenden SQL-Statements an:
'INSERT INTO produkte ...:artikel_gruppe, :artikel_name, :artikel_ausfuehrung, ' .
':artikel_detail)';

und
INSERT INTO preise ...:artikel_gruppe, :artikel_name, :artikel_auflage, :artikel_preis)';
Artikel-Gruppe und Artikel-Name werden also in 2 verschiedenen Tabellen geführt, das kann nicht richtig sein. Es müßte eine Artikel-Id geben, und die fungiert als Primärschlüssel in der Artikeltabelle und als Fremdschlüssel in allen anderen beteiligten Tabellen.
Wenn Du möchtest, kannst Du ja Deine Datenstruktur hier einmal posten.
 
Zurück
Oben