Bernd: Zwei INSERT mit einem Befehl?

Hallo,

ich benötige zwei INSERT mit einem Unterschiedlichem Text. Muss ich das INSERT dann zweimal ausführen wie ich es jetzt auch mache oder kann man dieses in ein INSER verpacken?

if ($stmt = $mysqli->prepare("INSERT INTO historie (
       ph_userid, 
       ph_projektid, 
       ph_was, 
       ph_datum, 
       ph_uhrzeit
     ) VALUES (?, ?, ?, ?, ?)")) { 
	        
	     $ph_userid   	= $object->user_code;
	     $ph_projektid  = $p_code;
	     $ph_was			  = "PDF wurde hochgeladen";
	     $ph_datum      = date("d.m.Y");
       $ph_uhrzeit   	= date("H:i:s");     
	        
	  $stmt->bind_param("sssss", $ph_userid, $ph_projektid, $ph_was, $ph_datum, $ph_uhrzeit);
	        
	  $stmt->execute(); 
    } else {
	    echo $mysqli -> error;
	}

Im zweiten INSERT müsste nur der Inhalt von $ph_was ausgetauscht werden.

  1. Tach!

    ich benötige zwei INSERT mit einem Unterschiedlichem Text. Muss ich das INSERT dann zweimal ausführen wie ich es jetzt auch mache oder kann man dieses in ein INSER verpacken?

    Das ist das Wesen von Prepared Statements, dass man das Statement einmal präpariert und dann mehrfach ausführen (execute) kann. Dazu die Werte der gebundenen Variablen nach Bedarf ändern und dann execute erneut ausführen.

    dedlfix.

  2. Ja. Man kann mehrere Inserts mit mysqli->multi_query($sql) machen lassen. Dabei gibt man aber auch Kontrolle ab. (last insert id, last error ...)

    Bevor Du das machst solltest Du Dir aber meine Kritik reinziehen:

    1.)

    $ph_projektid  = $p_code;
    

    Es ist in den meisten Fällen zwar kein "Fehler" aber unsinnig, Variablen umherzukopieren. Vorliegend ist ein Zeichen dafür, dass $p_code in eine Spalte ph_projektid eingetragen werden soll.

    Guter Rat: Verwende gleich Variablennamen, die der Spalte entsprechen. Das vermeidet logische Programmfehler, denn Du verwirrst Dich durch das "Bäumchen wechsle Dich" selbst. Nicht existierende Programmzeilen können keine Fehler enthalten.

    2.)

    Du verwendest eine Spalte für das Datum und eine für die Uhrzeit. MySQL kann das in einer Spalte. Datentyp DATETIME oder TIMESTAMP. Die aktuelle Zeit kann man dort mit NOW() eintragen, noch besser in der Tabellendefinition das mit "DEFAULT CURRENT_TIMESTAMP" festlegen - statt mit PHP rumzufummeln. Dann brauchst Du Datum und Uhrzeit gar nicht mehr zur Datenbank übertragen.

    3.)

    Offenbar ist das eine Art Logfile. Mir ist nicht ganz klar, warum Du für den Folgeeintrag, bei dem alles andere als der zu loggende Text (Benutzer, Projekt, Datum und Uhrzeit) identisch sein soll, nicht einfach beide Texte zu einem Eintrag zusammenfügst.

    1. Hallo,

      Es ist in den meisten Fällen zwar kein "Fehler" aber unsinnig, Variablen umherzukopieren. Vorliegend ist ein Zeichen dafür, dass $p_code in eine Spalte ph_projektid eingetragen werden soll. Guter Rat: Verwende gleich Variablennamen, die der Spalte entsprechen. Das vermeidet logische Programmfehler, denn Du verwirrst Dich durch das "Bäumchen wechsle Dich" selbst. Nicht existierende Programmzeilen können keine Fehler enthalten.

      zu mir hat mal einer gesagt, wenn deine Felder im HTMl Code gleich heißen wie die Felder in der Datenbank, hat es ein Angreifer umso einfacher. Deshalb nutze ich hier gerne unterschiedliche Namen.

      2.)

      Du verwendest eine Spalte für das Datum und eine für die Uhrzeit. MySQL kann das in einer Spalte. Datentyp DATETIME oder TIMESTAMP. Die aktuelle Zeit kann man dort mit NOW() eintragen - statt mit PHP rumzufummeln.

      dieses ist mir jetzt auch klar, dass ich vor Jahren ein Fehler gemacht habe. Diesen anzupassen wäre extrem viel Aufwand, da auf diese Tabelle mehrere Scripte drauf zugreifen. Also lass ich es erstmal so. Schadet meiner Meinung nach nicht.

      3.)

      Offenbar ist das eine Art Logfile. Mir ist nicht ganz klar, warum Du für den Folgeeintrag, bei dem alles andere als der zu loggende Text (Benutzer, Projekt, Datum und Uhrzeit) identisch sein soll, nicht einfach beide Texte zu einem Eintrag zusammenfügst.

      Weil ich nach Einträge suchen möchte. Außerdem wird in jedem Logfile welches mir bis jetzt zu Gesicht gekommen ist, jeder Eintrag separat gespeichert.

      1. zu mir hat mal einer gesagt, wenn deine Felder im HTMl Code gleich heißen wie die Felder in der Datenbank, hat es ein Angreifer umso einfacher.

        Vermutlich ist der an einer Überdosis Scherzkekse gestorben. Oder hat sich totgelacht, als Du ihm das geglaubt hast. Im Ernst: Entweder ist das ein Scherz oder der Typ war auch nicht klüger als der, dem er diesen Mist vortrug. Übrigens bist Du im PHP-Code.

        Außerdem wird in jedem Logfile welches mir bis jetzt zu Gesicht gekommen ist, jeder Eintrag separat gespeichert.

        Dann ist Dein Vorgehen dennoch logisch falsch.

        Das richtige Vorgehen ist:

        Ereignis 1 -> loggen
        Ereignis 2 -> loggen
        Ereignis 3 -> loggen
        

        Du willst:

        Ereignis 1
        Ereignis 2
        Ereignis 3
        -> alle loggen
        

        Was, wenn nach Ereignis 1 ein nicht behebbarer Fehler auftritt? Richtig: Es wird nicht geloggt.

        dieses ist mir jetzt auch klar, dass ich vor Jahren ein Fehler gemacht habe. Diesen anzupassen wäre extrem viel Aufwand,

        Wat mutt, mutt!

        Vermutlich da noch ein Fehler: ungenügende Isolierung des Loggens in einer austauschbaren Funktion und oder einem austauschbaren Objekt.

        1. Vermutlich da noch ein Fehler: ungenügende Isolierung des Loggens in einer austauschbaren Funktion und oder einem austauschbaren Objekt.

          Falls es Dein Server ist (Du also root-Rechte hast), dann würde ich an Deiner Stelle auch mal bei rsyslog nachlesen und dann die Dokumentation zu error_log() zu Rate ziehen. Der Rest? Siehe austauschbares Objekt oder Funktion.

      2. Tach!

        zu mir hat mal einer gesagt, wenn deine Felder im HTMl Code gleich heißen wie die Felder in der Datenbank, hat es ein Angreifer umso einfacher. Deshalb nutze ich hier gerne unterschiedliche Namen.

        Naja, sich selbst das Leben schwer machen, ist nicht die beste Lösung. Lieber verstehen, wie die Angriffe erfolgen, und richtige Gegenmaßnahmen verwenden, als Security by Obscurity.

        dedlfix.

    2. Tach!

      Ja man kann mehrere Inserts mit mysqli->multi_query($sql) machen.

      Lieber nicht, wenn man schon bei Prepared Statements ist, dann besser diese (aus)nutzen als komplett auf den herkömmlichen Ansatz umzusteigen.

      1.)

      $ph_projektid  = $p_code;
      

      Es ist in den meisten Fällen zwar kein "Fehler" aber unsinnig, Variablen umherzukopieren. Vorliegend ist ein Zeichen dafür, dass $p_code in eine Spalte ph_projektid eingetragen werden soll.

      Es ist im Falle von Prepared Statements mit der mysqli-Extension nicht verkehrt, für die Bind-Variablen lieber separate Variablen zu verwenden anstatt die eigentlichen Wertecontainer dafür zu verwenden. Diese Bindung erzeugt nämlich eine Referenz und die schleppt man dann dort rum, wo man sie gar nicht haben möchte.

      Guter Rat: Verwende gleich Variablennamen, die der Spalte entsprechen. Das vermeidet logische Programmfehler, denn Du verwirrst Dich durch das "Bäumchen wechsle Dich" selbst. Nicht existierende Programmzeilen können keine Fehler enthalten.

      Benennung von Dingen ist eine der großen Herausforderungen beim Programmieren, soweit stimme ich zu. Aber nicht beachtete Eigenheiten, die Auswirkungen auf andere Codeteile haben können, sind unangenehmer als Code, der Werte kopiert.

      Du verwendest eine Spalte für das Datum und eine für die Uhrzeit. MySQL kann das in einer Spalte. Datentyp DATETIME oder TIMESTAMP.

      Unangenehmer ist eher, dass das wohl String-Felder sind. Damit kann man nicht ohne Konvertierung mit den Datums- und Zeit-Funktionen arbeiten.

      3.) Offenbar ist das eine Art logfile. Mir ist nicht ganz klar, warum Du für den Folgeeintrag, bei dem alles andere als der zu loggende Text (Benutzer, Projekt, Datum und Uhrzeit) identisch sein soll, nicht einfach beide Texte zu einem Eintrag zusammenfügst.

      Kommaseparierte Einträge haben wieder andere Nachteile. Das muss man schon anhand des Anwendungsfalles bewerten, ob man nicht lieber doch Einzeleinträge haben möchte.

      dedlfix.

  3. Hallo Bernd,

    wenn es denn so sein soll, kannst Du einem INSERT auch mehr als eine Value-Liste mitgeben. Pro Value-Liste wird ein neuer Satz erzeugt.

    INSERT INTO historie (ph_userid, ph_projektid, ph_was, ph_datum, ph_uhrzeit)
        VALUES (?, ?, ?, ?, ?),
               (?, ?, ?, ?, ?)
    

    Vorteile:

    • Ein Turnaround weniger zum SQL Server.
    • Es ist ein Statement, d.h. entweder klappt alles oder nichts

    Nachteil:

    • Du musst doppelt so viele Parameter binden (wobei man meines Wissens eine Variable auch doppelt binden kann, du brauchst also nicht $ph_userid1 und $ph_userid2, etc.)

    Schöner wär's mit PDO, das kennt benannte Parameter. Aber unter der Haube wird auch nichts anderes passieren.

    Rolf

    --
    sumpsi - posui - clusi