MB: PDO multi inserts in einem rutsch

moin, moin,

Wie kann man einzufügende multiple datensätze in einem statement binden und dann zur datenbank schicken???

$sql = "INSERT INTO `tbl_article`( title, caption, content ) VALUES ( ?, ?, ? );";

In Meinem Objekt ist ein numerisches Array. Das beinhaltet ein assoziatives Array bestehend aus caption und content. So.:

$article = [
    'title' => 'Impressum',
    'abstract' => [
        [
           'caption' => 'Inhalt',
           'content' => '...'
        ], [
           'caption' => 'Haftung',
           'content' => '...'
        ], [
           'caption' => 'Links',
           'content' => '...'
        ]
    ]
];

Ich müsste dann sehr lahm drei transaktionen mit der Datenbank erledigen:

$sql1 = "INSERT INTO `tbl_article`( title, caption, content ) VALUES ( ?, ?, ? );",
'Impressum', 'Inhalt', '...';

$sql2 = "INSERT INTO `tbl_article`( title, caption, content ) VALUES ( ?, ?, ? );",
'Impressum', 'Haftung', '...';

$sql3 = "INSERT INTO `tbl_article`( title, caption, content ) VALUES ( ?, ?, ? );",
'Impressum', 'Links', '...';

Ich hab das natürlich mit for-Schleifen gemacht. Nur der übersichtlichkeit halber. Es sind nur 3 aber kann ende offen sein.

Ist es Möglich sicher mit prepared statements zu arbeiten und multiple datensätze in einem rutsch rüber zu schicken???

lg

  1. Tach!

    Wie kann man einzufügende multiple datensätze in einem statement binden und dann zur datenbank schicken???

    Dafür wurden die Prepared Statement erfunden, dass man einmal vorbereitet (prepare) und bindet und dann mehrfach Variableninhalte aktualisiert und ausführt (execute).

    dedlfix.

    1. hi dedlfix,

      Wie kann man einzufügende multiple datensätze in einem statement binden und dann zur datenbank schicken???

      Dafür wurden die Prepared Statement erfunden, dass man einmal vorbereitet (prepare) und bindet und dann mehrfach Variableninhalte aktualisiert und ausführt (execute).

      tut mir leider. Mir iust nicht soo ganz klar was du ausdrücken willst. Ich zum, nbeispiel habs mit dieser methode gemacht.

      try {
        $statement = self::$handler->prepare( $query );
        $statement->execute( $params );
        $result = $cargo( $statement ); // callable
      } catch( PDOException $ex ) {
        throw new Exception( $ex );
      }
      

      lg

      1. Tach!

        tut mir leider. Mir iust nicht soo ganz klar was du ausdrücken willst. Ich zum, nbeispiel habs mit dieser methode gemacht.

        try {
          $statement = self::$handler->prepare( $query );
          $statement->execute( $params );
          $result = $cargo( $statement ); // callable
        } catch( PDOException $ex ) {
          throw new Exception( $ex );
        }
        

        Mit PDO kann man den beschriebenen Prozess abkürzen, da muss man nur das Execute mehrfach ausführen und dabei jedes Mal neue Daten übergeben.

        Prepared Statements, so wie sie auch mit PDO verwendet werden können, sind dafür da, dass man dasselbe Statement mehrfach mit anderen Daten ausführen kann. Du machst also sinngemäß

        prepare("sql statement");
        execute($datensatz1);
        execute($datensatz2);
        execute($datensatz3);
        ...
        

        dedlfix.

        1. prepare("sql statement");
          execute($datensatz1);
          execute($datensatz2);
          execute($datensatz3);
          ...
          

          ok, ok. Meine frage is. kann man das abkürzen? z.B. so ...

          prepare("sql statement");
          execute( [ $datensatz1, $datensatz2, $datensatz3, ... );
          
          1. Tach!

            ok, ok. Meine frage is. kann man das abkürzen? z.B. so ...

            Alles was man mit den PHP-Funktionen machen kann, steht im Handbuch. Beschreibt es, dass die Funktion mit mehr als den Daten für ein Statement aufgerufen werden kann?

            Selbst wenn, würde sie auch nur einzelne Aufrufe im Hintergrund durchführen können. Damit ist nichts gewonnen. Hinzu kommt noch, dass man dann nicht herausfinden kann, bei welchen Werten es zu einem eventuellen Fehler gekommen ist.

            dedlfix.

  2. Hallo MB,

    mit prepared statements reduzierst Du den Overhead für das Compilieren des SQL in den Ausführungsplan, aber die Anzahl der Server-Turnarounds verringert sich nicht. Im Gegenteil, du bekommst für den Prepare einen dazu.

    Deswegen bringt das meines Erachtens nichts für die Performance eines einzelnen INSERT. Der Prepare bringt Dir aber gebundene Parameter und erleichtert Dir den Kontextwechsel für die einzufügenden Daten. Deswegen ist es schon ok, ihn zu verwenden.

    Für bessere Performance, sprich weniger Server-Turnarounds, kannst Du mit mehrfachen Valuelisten arbeiten:

    INSERT INTO tabelle (colA, colB, colC) VALUES (1,2,3), (4,5,6), (7,8,9)
    

    fügt 3 Zeilen auf einmal ein.

    Für Mengen-Inserts solltest Du überlegen, ob Du die IMPORT-Funktionen des SQL Servers verwenden kannst.

    Rolf

    --
    sumpsi - posui - clusi
    1. Hi RolfB,

      Gut das du das SQL anführst. Ich wollt wissen ob man auch soiwas machen kann.

      $query = "INSERT INTO tabelle (colA, colB, colC) VALUES (?, ?, ?);";
      

      ... oder vielleicht sogar so ...

      $query = "INSERT INTO tabelle (colA, colB, colC) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?);";
      $param = [ [1,2,3], [4,5,6], [7,8,9] ];
      
      $handler->prepare( $query );
      $statement->execute( $params );
      

      Das war eigentlich nur meine frage. Sr wenn ich es undeutlich rübergebracht habe.

      lg

      1. Tach!

        Gut das du das SQL anführst. Ich wollt wissen ob man auch soiwas machen kann.

        $query = "INSERT INTO tabelle (colA, colB, colC) VALUES (?, ?, ?);";
        

        ... oder vielleicht sogar so ...

        $query = "INSERT INTO tabelle (colA, colB, colC) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?);";
        

        Wenn du beides als jeweils ein Statement betrachtest ... natürlich. Das MySQL-Handbuch beschreibt eine solche Syntax.

        $param = [ [1,2,3], [4,5,6], [7,8,9] ];

        Nicht verschachtelt, es ist nur ein Statement und das nimmt einen Satz Daten an, also ein flaches Array für execute(). Dass du damit drei Datensätze anlegst, steht auf einem anderen Blatt.

        dedlfix.

        1. Hallo,

          was man dabei leider in Kauf nehmen muss, ist, dass man die Anzahl der zu INSERTenden Sätze nicht flexibel halten kann. Das Statement enthält 3 Valuelisten und will darum auch gnadenlos 3 Sätze anlegen. Selbst mit Routinen (Stored Procedures) kommt man nicht weiter, weil MYSQL keine Array Parameter kennt.

          D.h. man muss bei umfangreicheren Inserts einen mehrfach-Insert für bspw. 10 Sätze verwenden und einen Einzel-Insert für die letzten 1-9 Sätze.

          Rolf

          --
          sumpsi - posui - clusi
    2. hi @Rolf B

      Deswegen bringt das meines Erachtens nichts für die Performance eines einzelnen INSERT.

      Doch, bringt es. Ein Multiple Insert ist wesentlich (!) performanter als mehrere Inserts derselben Datenmenge über prepared Statements.

      Der Crux an der Sache ist nur, daß multiple Inserts keine ausreichende Fehlerbehandlung ermöglichen bzw. einen höheren Aufwand erfordern diezbezüglich.

      MfG

      1. Hallo pl,

        du hast ungenau gelesen und ich habe ungenau formuliert.

        Ich habe darüber gesprochen, ob ein PREPARE für einen INSERT überhaupt Performance-Vorteile haben kann. Selbst wenn man das PREPAREte Statement 1000x ausführt. Ich würde bezweifeln, dass der Execution Plan für ein INSERT aufwändig zu bestimmen ist (und abgesehen davon cached ein SQL Server die Execution Plans auch für nicht PREPAREte Statements).

        Der Nutzen des Prepare liegt hier vor allem in der Nutzung von Hostvariablen, nicht in der Performance.

        Die Performance gewinnt man über den Einsatz von mehr als einer Value-Liste. Da sind wir uns einig.

        Rolf

        --
        sumpsi - posui - clusi