Markus**: mySQL und Perl

Folgender code:

$sth=$dbh->prepare($statement);
  $sth->execute();
  $rows=$sth->rows;
  $sth->finish();
  return($rows);

sollte die Anzahl der betroffenen Zeilen zurückgeben, nicht wahr? Und die Datenbank sollte da "0" zurückgeben, wenn ich ein "UPDATE" ausführe, was nichts bewirkt. Tut's aber nicht.... es gibt immer mindestens "1" bzw. "-1" (siehe unten) zurück...

man - woran liegt das?

aus der Doku:

$sth->rows

Returns the number of rows affected by the last row affecting command, or -1 if the number of rows is not known or not available.

  1. hi,

    Folgender code:

    $sth=$dbh->prepare($statement);
      $sth->execute();
      $rows=$sth->rows;
      $sth->finish();
      return($rows);

    sollte die Anzahl der betroffenen Zeilen zurückgeben, nicht wahr? Und die Datenbank sollte da "0" zurückgeben, wenn ich ein "UPDATE" ausführe, was nichts bewirkt. Tut's aber nicht.... es gibt immer mindestens "1" bzw. "-1" (siehe unten) zurück...

    man - woran liegt das?

    Stimmt Dein Statement, funktioniert das auch außerhalb von Perl?

    aus der Doku:

    $sth->rows

    Returns the number of rows affected by the last row affecting command, or -1 if the number of rows is not known or not available.

    Mit rows() hatte ich auch mal Probleme, die ich nicht nachvollziehen konnte. Seitdem benutze ich count(spaltenname);

    Viele Grüße,
    Hotte

    1. $sth->rows

      Returns the number of rows affected by the last row affecting command, or -1 if the number of rows is not known or not available.

      Mit rows() hatte ich auch mal Probleme, die ich nicht nachvollziehen konnte. Seitdem benutze ich count(spaltenname);

      Bei einem Update?

      Struppi.

    2. Stimmt Dein Statement, funktioniert das auch außerhalb von Perl?

      aber klar - das hab ich längst probiert!

      Mit rows() hatte ich auch mal Probleme, die ich nicht nachvollziehen konnte. Seitdem benutze ich count(spaltenname);

      nutzt mir nichts, ich möchte bitte wissen wiviele Datensätze GEÄNDERT wurden. Das kann halt im Zweifel KEINER sein, wenn das UPDATE query IDENTISCHE einträge überschreiben WILL.

      thanks und Gruß,
         Markus

  2. hi,

    $sth=$dbh->prepare($statement);
      $sth->execute();
      $rows=$sth->rows;
      $sth->finish();
      return($rows);

    sollte die Anzahl der betroffenen Zeilen zurückgeben, nicht wahr? Und die Datenbank sollte da "0" zurückgeben, wenn ich ein "UPDATE" ausführe, was nichts bewirkt.

    Also ich hab das jetzt mal nachgebaut und es funktioniert so wie Du schreibst mit einer Tabelle vom Typ MyISAM. Evntl. hast Du einen anderen Tabellentyp der ein commit() erfordert.

    Viele Grüße,
    Horst Haselhuhn

    1. mahlzeit!

      Also ich hab das jetzt mal nachgebaut und es funktioniert so wie Du schreibst mit einer Tabelle vom Typ MyISAM. Evntl. hast Du einen anderen Tabellentyp der ein commit() erfordert.

      Ich hab MyISQM Tabellen und bekomme "1" zuürck, wenn ich ein UPDATE ausführe was NICHTS ÄNDERT. Ich erwarte allerding die Rückgabe "0".

      "-1" kommt zurück, wenn das Ausführen des statements fehlschlägt
      und n kommt zurück wenn n datensätze verändert wurden.

      Mist! :)

      1. mahlzeit!

        Also ich hab das jetzt mal nachgebaut und es funktioniert so wie Du schreibst mit einer Tabelle vom Typ MyISAM. Evntl. hast Du einen anderen Tabellentyp der ein commit() erfordert.

        Ich hab MyISQM Tabellen und bekomme "1" zuürck, wenn ich ein UPDATE ausführe was NICHTS ÄNDERT. Ich erwarte allerding die Rückgabe "0".

        Da ist irgendwas faul, das muss gehen ;-)

        Poste mal DBI::Version; Perl-version, MySQL-Version zum Vergleich.

        Btw.,
        use strict;   # ?
        use warnings; # ?

        --Hotte

        1. OK!

          DBI: 1.602
          (Active)Perl: 5.8.0.804
          DBD-mysql: 3.0002
          mySQL: 5.0.18
          OS: Win2k SP4

          soweit dazu...

          Also: nochmal zur Prüfung: ich erzeuge das statement dynamisch, hab es mir einfach mal als Text ausgeben lassen und im PHPmyAdmin sowie im mySQL Command line probiert. Beide male bekomme ich "affected rows: 0" zurück, nur mein Perlscript gibt "1".

          Das darf doch wohl nicht wahr sein! *genervt ist*

          genervter Gruß,

          Markus

          1. OK!

            DBI: 1.602
            (Active)Perl: 5.8.0.804
            DBD-mysql: 3.0002
            mySQL: 5.0.18
            OS: Win2k SP4

            soweit dazu...

            Also: nochmal zur Prüfung: ich erzeuge das statement dynamisch, hab es mir einfach mal als Text ausgeben lassen und im PHPmyAdmin sowie im mySQL Command line probiert. Beide male bekomme ich "affected rows: 0" zurück, nur mein Perlscript gibt "1".

            Das darf doch wohl nicht wahr sein! *genervt ist*

            Hmm,

            $DBI::VERSION = "1.48"

            mysql  Ver 12.22 Distrib 4.0.18, for Win95/Win98 (i32)

            This is perl, v5.6.1 built for MSWin32-x86-multi-thread

            bei mir tut's. Evntl. ein Bug in den neureren Versionen, anders kann ich mir das jetzt auch nicht erklären.

            Viele Grüße,
            Hotte

            1. ich hoffe wir reden nicht aneinander vorbei ich hab hier nochmal geschrieben was ich erwarte...

              wie sieht den Dein "test-sql-statement" aus?

              Gruß, Markus

              1. ich hoffe wir reden nicht aneinander vorbei ich hab hier nochmal geschrieben was ich erwarte...

                wie sieht den Dein "test-sql-statement" aus?

                genauso wie Deins, ich mache in Update und zähle die affected rows:

                use strict;
                use lib '/var/www/vhosts/rolfrost.de/cgi-bin';
                use DBI;
                use Basic;

                my $dbh = connMySQL;

                my $st = qq(UPDATE spamprot SET zeitstempel = 4);

                my $sth=$dbh->prepare($st);
                $sth->execute();
                my $rows=$sth->rows;
                $sth->finish();

                print "$rows\n"; # und das stimmt ;-)

                --Hotte

                1. genauso wie Deins, ich mache in Update und zähle die affected rows:

                  use strict;
                  use lib '/var/www/vhosts/rolfrost.de/cgi-bin';
                  use DBI;
                  use Basic;

                  my $dbh = connMySQL;

                  my $st = qq(UPDATE spamprot SET zeitstempel = 4);

                  my $sth=$dbh->prepare($st);
                  $sth->execute();
                  my $rows=$sth->rows;
                  $sth->finish();

                  print "$rows\n"; # und das stimmt ;-)

                  und zurück kommt in dem Fall "1" :-) oder irre ich mich?

                  1. genauso wie Deins, ich mache in Update und zähle die affected rows:

                    use strict;
                    use lib '/var/www/vhosts/rolfrost.de/cgi-bin';
                    use DBI;
                    use Basic;

                    my $dbh = connMySQL;

                    my $st = qq(UPDATE spamprot SET zeitstempel = 4);

                    my $sth=$dbh->prepare($st);
                    $sth->execute();
                    my $rows=$sth->rows;
                    $sth->finish();

                    print "$rows\n"; # und das stimmt ;-)

                    und zurück kommt in dem Fall "1" :-) oder irre ich mich?

                    Zum Verständis (was wir beide haben):
                    Die Spalte zeitstempel bekommt ein update auf 4. Da keine whereKlause drin ist, werden alle records das Update bekommen, das sind bei mir 3 records und die 3 steht dann in $rows. In einem zweiten Durchlauf ist $rows == 0, weil sich per update keine Änderung ergab.

                    Mache ich einen dritten Durchlauf mit
                    my $st = qq(UPDATE spamprot SET zeitstempel = 5);

                    zeigt mir $rows wiederum, dass 3 rows vom update betroffen sind.

                    Schade, dass das bei Dir nicht so tut, aber wie gesagt, ich vermute einen oder mehrere Bugs. Schraub Dich mal durch CPAN und die Repository vom DBI.pm, vielleicht wirst Du da fündig.

                    Evntl. ist auch
                    use strict;
                    use warnings;

                    im PerlCode hilfreich, nicht dass da der Hase im Pfeffer liegt.

                    --Hotte

                    1. Schade, dass das bei Dir nicht so tut, aber wie gesagt, ich vermute einen oder mehrere Bugs. Schraub Dich mal durch CPAN und die Repository vom DBI.pm, vielleicht wirst Du da fündig.

                      Du solltest ein bisschen mitlesen. er will Wissen ob etwas geändert wurde, nicht wieviel.

                      Struppi.

                      1. er will Wissen ob etwas geändert wurde, nicht wieviel.

                        trifft's exakt!

                      2. hi,

                        Schade, dass das bei Dir nicht so tut, aber wie gesagt, ich vermute einen oder mehrere Bugs. Schraub Dich mal durch CPAN und die Repository vom DBI.pm, vielleicht wirst Du da fündig.

                        Du solltest ein bisschen mitlesen. er will Wissen ob etwas geändert wurde, nicht wieviel.

                        Na Du bist villeicht ein IT-Experte ;-)

                        Schau mal, so einfach gehts mit einer Kontrollstruktur in Perl:

                        if( $sth->rows == 0 ){ # nichts wurde geändert }
                        elsif( $sth->rows == -1 ){ # das Statement ging schief }
                        else{ # es wurde was geändert }

                        Viele Grüße,
                        Horst

                        1. Na Du bist villeicht ein IT-Experte ;-)

                          Im gegensatz zu dir hab ich aber verstanden worum es Markus geht.

                          Schau mal, so einfach gehts mit einer Kontrollstruktur in Perl:

                          Das löst nach wie vor nicht das Problem von Markus

                          Struppi.

                    2. Schade, dass das bei Dir nicht so tut, aber wie gesagt, ich vermute einen oder mehrere Bugs. Schraub Dich mal durch CPAN und die Repository vom DBI.pm, vielleicht wirst Du da fündig.

                      Mist, werd' ich wohl tun müssen :-/ Mannoooo! Das kann doch nicht sein, dass das vor mir noch keiner gemerkt hat! :/

                      1. Mist, werd' ich wohl tun müssen :-/ Mannoooo! Das kann doch nicht sein, dass das vor mir noch keiner gemerkt hat! :/

                        Ich mach solche Prüfungen in meiner Anwendung. Oft macht man ja einen update auf einen Datensatz, den man vorher bearbeitet.

                        Struppi.

                      2. Schade, dass das bei Dir nicht so tut, aber wie gesagt, ich vermute einen oder mehrere Bugs. Schraub Dich mal durch CPAN und die Repository vom DBI.pm, vielleicht wirst Du da fündig.

                        Mist, werd' ich wohl tun müssen :-/ Mannoooo! Das kann doch nicht sein, dass das vor mir noch keiner gemerkt hat! :/

                        Ich gebe zu, dass mir die DBI-Funktion rows() auch erst heute so richtig klar geworden ist im Dialog mit Dir und mit einem eigens dazu gebauten Script.

                        Warum das bei Dir nicht tut, keine Ahnung. Möglicherweise Bug.

                        Viele Grüße,
                        Hotte

                2. my $sth=$dbh->prepare($st);
                  $sth->execute();
                  my $rows=$sth->rows;

                  Das ist nicht notwendig, execute gibt die Anzahl der Reihen bereits zurück.
                  http://search.cpan.org/~timb/DBI/DBI.pm#execute

                  For a non-SELECT statement, execute returns the number of rows affected, if known. If no rows were affected, then execute returns "0E0", which Perl will treat as 0 but will regard as true. Note that it is not an error for no rows to be affected by a statement. If the number of rows affected is not known, then execute returns -1.

                  Struppi.

                  1. my $sth=$dbh->prepare($st);
                    $sth->execute();
                    my $rows=$sth->rows;

                    Das ist nicht notwendig, execute gibt die Anzahl der Reihen bereits zurück.

                    genau das hab ich auch schon festgestellt, trotzdem komm ich nicht an mein gewünschte Ziel ohne mittels SELECT zu prüfen ob eine Änderung vorgenommen wurde oder nicht! :-/ sehr unschön!

                    Gruß, Markus

                    1. my $sth=$dbh->prepare($st);
                      $sth->execute();
                      my $rows=$sth->rows;

                      Das ist nicht notwendig, execute gibt die Anzahl der Reihen bereits zurück.
                      genau das hab ich auch schon festgestellt, trotzdem komm ich nicht an mein gewünschte Ziel ohne mittels SELECT zu prüfen ob eine Änderung vorgenommen wurde oder nicht! :-/ sehr unschön!

                      Ich weiß das bereits und mir ist keine Lösung bekannt.
                      Mir ging es nur um den Code von Rolf/Hotte/Hotti der den unnötigen Aufruf enthält.

                      Struppi.

    2. Vielleicht sollte ich nochmal in einfachen Worten mein Ziel beschreiben! ;)

      Ich möchte feststellen ob ein "UPDATE table_name SET y = 'wert'" den Datenbestand verändert oder nicht.

      Gruß, Markus

      1. Vielleicht sollte ich nochmal in einfachen Worten mein Ziel beschreiben! ;)

        Ich möchte feststellen ob ein "UPDATE table_name SET y = 'wert'" den Datenbestand verändert oder nicht.

        In dem Fall, gibt der Update Befehl ein 0E0 zurück.

        Struppi.

        1. In dem Fall, gibt der Update Befehl ein 0E0 zurück.

          Das hab ich auch der Doku entnommen, bei mir kommt aber "1" zurück - warum zur Hölle? :)

          1. In dem Fall, gibt der Update Befehl ein 0E0 zurück.

            Das hab ich auch der Doku entnommen, bei mir kommt aber "1" zurück - warum zur Hölle? :)

            Dann machst du etwas falsch oder bei dir stimmt etwas nicht, bei mir kommt 0E0 zurück, wenn UPDATE nichts macht.

            Struppi.

            1. Dann machst du etwas falsch oder bei dir stimmt etwas nicht, bei mir kommt 0E0 zurück, wenn UPDATE nichts macht.

              Okay... hier mal mein Testcode:

                
              $statement = qq{  
               UPDATE bus_vehicle  
               SET  
               driver_name = 'Marcel Jansen',  
               driver2_name = 'Jogi Löw',  
               driver_cell = '123456767',  
               driver2_cell = '784357989',  
               driver_email = 'm.jansen@nationalmannschaft.de',  
               driver2_email = 'jogi@nationalmannschaft.de',  
               parking = 'outside',  
               passenger = '026',  
               bus_sign = 'ab-cd 123',  
               countrycode = '49',  
               countrycode2 = '49',  
               time_id = '21'  
               WHERE bus_id = '212'};  
                
                
              print query($statement);  
              print query($statement);  
                
              sub query  
                {  
                $sth=$dbh->prepare($_[0]);  
                $sth->execute();  
                $rows=$sth->rows;  
                $sth->finish();  
                return($rows);  
                exit;  
                }  
                
              
              

              Folgendes gibt 2x 1 aus - obwohl ja spätestens bei der zweiten print Anweisung 0 bzw. auch 0E0 zurück kommen sollte, oder? Hab ich heute eigentlich irgendwas völlig verrafft?

              Gruß, Markus

              1. Folgendes gibt 2x 1 aus - obwohl ja spätestens bei der zweiten print Anweisung 0 bzw. auch 0E0 zurück kommen sollte, oder? Hab ich heute eigentlich irgendwas völlig verrafft?

                Ach jetzt wird dein Problem klar. Soweit ich das sehe, kannst du nicht festellen ob der update überflüssig ist. Obwohl mysql diese Information bereit stellt, ich weiß aber nicht ob und wo DBI dieses Angaben abfragt.

                Struppi.

                1. Ach jetzt wird dein Problem klar. Soweit ich das sehe, kannst du nicht festellen ob der update überflüssig ist. Obwohl mysql diese Information bereit stellt, ich weiß aber nicht ob und wo DBI dieses Angaben abfragt.

                  Struppi.

                  Aha... da haben wir es doch! ;) Soll das heißen dass ich das also händisch prüfen muß? Arghl! Ich will doch nich vorm UPDATE ein SELECT durchführen um die Daten gegen zu prüfen... das ist ja... nein, das ist das was ich eigentlich NICHT will. Aber offenbar bleibt mir ja nichts anderes übrig :-/

                  Oder hat jemand ne patentere Idee? Ich lese derweil nochmal die DBI perldoc.

                  Gruß, Markus

                  1. Oder hat jemand ne patentere Idee? Ich lese derweil nochmal die DBI perldoc.

                    Für UPDATEs wird generell do empfohlen, wie sieht es dann bei Dir aus? Ansonsten sagt die Dokumentation:

                    "For a non-SELECT statement, execute returns the number of rows affected, if known. If no rows were affected, then execute returns "0E0", which Perl will treat as 0 but will regard as true. Note that it is not an error for no rows to be affected by a statement. If the number of rows affected is not known, then execute returns -1."

                    Mach also mal spaßeshalber

                    $rows = $sth->execute;

                    Siechfred

                    --
                    Hinter den Kulissen passiert viel mehr, als man denkt, aber meistens nicht das, was man denkt.
                    1. Für UPDATEs wird generell do empfohlen, wie sieht es dann bei Dir aus?

                      Mach also mal spaßeshalber

                      $rows = $sth->execute;

                      ja, dann kommt 1 zurück, auch wenn nichts geänder wird - darum geht's ja die ganze Zeit! :-) Same shit wenn ich do() benutze. Also?

                      Gruß, Markus

          2. In dem Fall, gibt der Update Befehl ein 0E0 zurück.

            Das hab ich auch der Doku entnommen, bei mir kommt aber "1" zurück - warum zur Hölle? :)

            Ach, ich meine die do() Funktion nicht rows

            Struppi.

  3. Erstmal einen Dank an Euch auf für die Hilfe!

    Ich fand folgenden Eintrag in einer Newsgroup, der die Problematik und eine Lösung schildert. Es ist ein konfigurations-problem!
    -----------------------------------------

    Hmmm, I forgot about this outstanding issue. This is a known behaviour
    of the MySQL engine, call it a bug or a feature, as you like. (It declares
    "affected" as "changed".) The behaviour you are expecting can be enabled
    by setting the C flag CLIENT_FOUND_ROWS when connecting to the database.

    I have now uploaded a version 1.2205 of the Msql-Mysql-modules to CPAN
    which has the following new feature: When connecting with

    DBI->connect("DBI:mysql:test;mysql_client_found_rows=0", ...)

    then you have the old behaviour. With

    DBI->connect("DBI:mysql:test;mysql_client_found_rows=1", ...)

    you have CLIENT_FOUND_ROWS set, thus your query will always return 1.

    The default is 0, however you can change this by compiling the
    Msql-Mysql-modules with

    perl Makefile.PL --config --mysql-use-client-found-rows

    in which case the default is 1.

    Monty, I dislike that this must be choosen while connecting to the
    client. Couldn't we make this part of the MYSQL structure?

    -----------------------------------------
    Quelle: http://lists.mysql.com/perl/250?f=plain

    Gruß, Markus

    1. Lange und gut gesucht, vermute ich mal  ;-)

      Monty, I dislike that this must be choosen while connecting to the
      client. Couldn't we make this part of the MYSQL structure?

      Das haben sie wohl umgesetzt.

      Die Frage ist, wenn du das in der mySql Konsole machst erhälst du tasächlich zwei Werte, rows und changed, bei einer Änderung wo nichts passiert, ist rows 1 und changed 0, d.h. mysql gibt eigentlich diese Information preis, warum bekommt das Modul das nicht.

      Struppi.

      1. Lange und gut gesucht, vermute ich mal  ;-)

        Die Frage ist, wenn du das in der mySql Konsole machst erhälst du tasächlich zwei Werte, rows und changed, bei einer Änderung wo nichts passiert, ist rows 1 und changed 0, d.h. mysql gibt eigentlich diese Information preis, warum bekommt das Modul das nicht.

        Jo. Hab allerdings nach der Diskussion hier, ziemlich genau gewusst was nach was ich bei google suchen muß! ;) "CPAN DBI mySQL BUG affected rows" hat mir das gewünschte Resultat gebracht.

        Denke das Modul bzw. der treiber bekommt die Werte, allerdings werden sie nicht _BEIDE_ weiterverarbeitet, bzw. man muß definieren welchen man "sehen" möchte.
        Who knows?!

        Gruß´, Markus