insert-select mit "null"-werten

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • insert-select mit "null"-werten

    hallo *all,

    bin neu in php und mysql und habe folgendes problem:

    2 identische datenbanken auf verteilten systemen, die eine ist produktiv, die andere dient als backup und wird täglich mit einem php-script ausgelesen und teilweise rüberkopiert.

    das ganze mache ich mit select, implode und insert. der umweg muß sein, weil durch die verteilten systeme 2 connects fällig sind, mein sql-statement aber nur 1 connect verträgt.

    das klappt auch alles 100%.

    problem jedoch: die table enthält eine INT-spalte, in der die werte "NULL", 0, 1, etc drin stehen und dies wird mir beim kopieren zerstört.

    also:

    srcTable --> trgTable
    NULL --> 0
    0 --> 0
    4711 --> 4711

    hilfe!!!!

    was kann man tun??? die struktur der tables ist identisch, die mysql-versionen auch, php auch, alles gleich.

    für einen tipp oder eine lösung wäre ich sehr dankbar.

    lg, karin

  • #2
    Re: insert-select mit "null"-werten

    Original geschrieben von karin-v
    das ganze mache ich mit select, implode und insert.
    Kann mir darunter leider nicht viel vorstellen, Zeige mal etwas von deinem Code.

    Eigentlich gäbe es für solche Fälle ja das Tool mysql_dump, oder auch die Befehle SELECT ... INTO und LOAD DATA ..., aber vielleicht hast du ja Gründe, das anders zu machen.
    Gruss
    H2O

    Kommentar


    • #3
      Du musst prüfen, ob ein Nullwert in der Datenbank stand und dies entsprechend wieder einfügen:
      PHP-Code:
      $query "insert into tabelle ".
        
      "set value1=".( is_null$value1 ) ? 'NULL' $value1 ).", ".
        
      "    value2=".( is_null$value2 ) ? 'NULL' $value2 ).", ".
       
      // ... 

      Kommentar


      • #4
        das kopieren geht so (connect's und prüfungen mal ausgelassen, hinweis: es dürfen immer nur bestimmte zeiträume kopiert werden, deshalb die WHERE-bedingung):


        // Quell-Tabelle lesen und in Ziel-Tabelle schreiben
        //
        $srcResult = mysql_query("select * from $srcDB.$srcTable
        where $srcColVergleich < (from_days(to_days(curdate()) - 0))
        and $srcColVergleich >= '$lastReorgDate' " , $srcConnect);


        // Weiter: jeden Satz einzeln nehmen und in die Ziel-Tabelle inserten
        //
        while ($row = mysql_fetch_array($srcResult, MYSQL_ASSOC)) {

        $trgResult = mysql_query("insert into $trgDB.$trgTable (".implode(", ",array_keys($row)).") values ('".implode("', '",array_values($row))."') ",
        $trgConnect);

        }

        kommst du klar?

        Kommentar


        • #5
          Original geschrieben von PHP-Desaster
          Du musst prüfen, ob ein Nullwert in der Datenbank stand und dies entsprechend wieder einfügen:
          PHP-Code:
          $query "insert into tabelle ".
            
          "set value1=".( is_null$value1 ) ? 'NULL' $value1 ).", ".
            
          "    value2=".( is_null$value2 ) ? 'NULL' $value2 ).", ".
           
          // ... 
          Das dürfte nicht funktionieren.
          NULL ist ein interner Wert von MySQL, im Result-Set steht nur "", d.h. entweder gibt is_null() fälschlicherweise bei jedem leeren String 'true' zurück, oder immer 'false'.

          Ein netter Guide zum übersichtlichen Schreiben von PHP/MySQL-Code!

          bei Klammersetzung bevorzuge ich jedoch die JavaCoding-Standards
          Wie man Fragen richtig stellt

          Kommentar


          • #6
            In $row steht bei Null-Werten NULL. In deinem implode() umgibst du nun alle Werte mit Anführungszeichen. Das ist schon bei nummerischen Werten unsauber, aber toleriert. Wenn nun aber NULL zu 'NULL' wird, und du nun diesen Wert in ein nummerisches Feld zu speichern versuchst, wird es als 0 interpretiert.
            Es bleibt dir vermutlich mit diesem Ansatz nichts anderes übrig, als auf implode() zu verzichten und die Felder einzeln abzuhandeln.
            Deshalb würde ich dir empfehlen die Daten mit SELECT .... INTO OUTFILE in eine Datei zu schreiben, und diese dann anschliessend mit LOAD DATA INFILE wieder einzulesen. Diese Methode ist wahrscheinlich auch schneller.
            Gruss
            H2O

            Kommentar


            • #7
              Das dürfte nicht funktionieren.
              NULL ist ein interner Wert von MySQL, im Result-Set steht nur "", d.h. entweder gibt is_null() fälschlicherweise bei jedem leeren String 'true' zurück, oder immer 'false'.
              Du weißt schon, dass das Käse ist??

              Code:
              CREATE TABLE test (
                id int(10)
              );
              
              INSERT INTO test VALUES (NULL);
              INSERT INTO test VALUES (1);
              PHP-Code:
              $pdo = new PDO$dsn$user$pass );
              foreach( 
              $pdo->query"select id from test" ) as $row ) {
                  
              var_dump$row['id'] );

              ergibt:
              Code:
              NULL
              string(1) "1"

              Kommentar


              • #8
                ok,
                ich werde mal das mit dem load data ausprobieren und mich wieder melden. wird ein bischen dauern, da ich die funktion noch nicht kenne und etwas üben muß.

                schon mal besten dank bis hierhin für die vielen infos!!!!

                lg, karin

                Kommentar


                • #9
                  Kannst deine implodes ja auch in meinen Vorschlag umbastelt. Brauchst ja lediglich vorher eine Schleife über deine Werte jagen!

                  Kommentar


                  • #10
                    Original geschrieben von PHP-Desaster
                    Kannst deine implodes ja auch in meinen Vorschlag umbastelt. Brauchst ja lediglich vorher eine Schleife über deine Werte jagen!
                    das sieht mir so aus, als müßte man dann die spaltennamen alle kennen. das ist jedoch nicht der fall., oder?

                    (hängt damit zusammen, daß mein script von einer steuerdatei befüttert wird und in der steuerdatei jede menge tabellen zum kopieren hinterlegt sind, die natürlich alle eine andere struktur haben...)

                    aber kein thema, ich werde alles ausprobieren, so lange, bis die nuller stimmen!

                    Kommentar


                    • #11
                      das sieht mir so aus, als müßte man dann die spaltennamen alle kennen. das ist jedoch nicht der fall., oder?
                      Nein, da du deine Werte in einem Array liegen hast, kannst du gut mit foreach arbeiten.

                      Kommentar


                      • #12
                        Selbstverständlich kannst du die mysql_field_name(), mysql_field_typ(), mysql_field_...-Funktionen benutzen, um das herauszufinden, und dann alles mühsam programmieren.
                        Aber wie gesagt, das gibts ja alles schon und mit vier Zeilen Code (pro Tabelle) (aus denen ich aus Gründen der Lesbarkeit ein paar mehr mache) bist du dabei:
                        PHP-Code:
                        $sql "
                            SELECT *
                            FROM 
                        $srcDB.$tabelle
                            INTO OUTFILE '/tmp/tab.out'
                            FIELDS TERMINATED BY ';'
                            OPTIONALLY ENCLOSED BY '\"'
                            LINES TERMINATED BY '\n'"
                        ;
                        $res mysql_query($sql) || die(mysql_error());

                        $sql "
                            LOAD DATA INFILE '/tmp/tab.out'
                            INTO TABLE 
                        $trgDB.$tabelle
                            FIELDS TERMINATED BY ';'
                            OPTIONALLY ENCLOSED BY '\"'
                            LINES TERMINATED BY '\n'"
                        ;
                        $res mysql_query($sql) || die(mysql_error()); 
                        Und für mehrere Tabellen hängst du das noch in eine Schleife und der ganze Backup ist programmiert:
                        PHP-Code:
                        foreach $tab_list as $tabelle{

                            
                        // code von vorher

                            
                        unlink('/tmp/tab.out');

                        Gruss
                        H2O

                        Kommentar


                        • #13
                          Vorteil des eigenen Codes ist aber ganz klar: Das funktioniert auch mit anderen DB-Systemen!

                          Kommentar


                          • #14
                            Original geschrieben von PHP-Desaster
                            Vorteil des eigenen Codes ist aber ganz klar: Das funktioniert auch mit anderen DB-Systemen!
                            Aber nicht mit den mysql_-Funktionen. Ausserdem läuft SELECT ... INTO OUTFILE und LOAD DATA ... auch mit Oracle. Bei andern Systemen weiss ich es nicht.
                            Gruss
                            H2O

                            Kommentar


                            • #15
                              Aber nicht mit den mysql_-Funktionen.
                              Na klar, dass nicht, aber ich gehe eh davon aus, das kein Mensch mehr direkt die Funktionen in seinen Skripten nutzt, sondern wenigstens einen Wrapper drumherum hat.
                              Ausserdem läuft SELECT ... INTO OUTFILE und LOAD DATA ... auch mit Oracle. Bei andern Systemen weiss ich es nicht.
                              Wenn weitere Systeme das auch implementieren, ist das nicht schlecht. Muss mal nachschlagen, ob der Befehl auch von weiteren Systemen angeboten wird.

                              Kommentar

                              Lädt...
                              X