[mysql5/php5] Statement zou moeten falen, maar doet dat niet

Pagina: 1
Acties:
  • 104 views sinds 30-01-2008
  • Reageer

  • Explore
  • Registratie: Maart 2001
  • Laatst online: 08-04-2011

Explore

Op zoek naar werk

Topicstarter
Volgens de php manual zou een 'execute' op een 'Statement' een 'false' moeten teruggeven als er iets fout gaat. Als ik in m'n MySQL client de query uit onderstaand stukje code uitvoer met een 'mykey' die niet bestaat in de tabel, dan krijg ik een error (code 1054). Ik verwacht dat de exucute dan false zou moeten geven en dat php dan de exception throwd.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
try {
    $oConnection = DbConnection::connect();
    $stmt = $oConnection->stmt_init();
    if ($stmt->prepare("update mytable set myfield=1 where mykey=?")) {
        $stmt->bind_param("s", $sMyKey);
        if (!$stmt->execute()) {
            throw new QueryFailedException($oConnection->error);
        }   
    }
    $stmt->close();
    DbConnection::close($oConnection);
} catch (Exception $e) {
    // something went wrong...
}


Klopt dit gedrag? Het blijkt wel mogelijk te zijn om de affected_rows op te vragen en als dat 0 is, mag je er van uit gaan dat er iets fout ging... Lijkt een beetje een omweg. Is dit een bug of mis ik iets?

Een andere, zijdelings gerelateerde vraag: is dit soort code traag in vergelijking met de standaard mysql?

Ik draai hier MySQL 5.0.18 en PHP 5.1.2 in combinatie met MySQL-Improved.

[ specs ] [ Tweaker gallery ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 11-03 14:33

NMe

Quia Ego Sic Dico.

Wanneer er 0 affected rows zijn, dan lijkt me dat niet per se een fout. Een voorbeeld: ik host een site voor een game, waarop ook de spelersdatabase staat opgeslagen, en ik hou ook bij wie er online is op de server. Wanneer de spelserver vastloopt, dan klopt datgeen dat in mijn database staat niet meer. Het eerste wat die server dus doet is tegen mijn webserver vertellen dat iedereen "uitgelogd" moet worden, wat neerkomt op een query:
SQL:
1
UPDATE `tabel` SET `online` = 0

Als iedereen toevallig al uitgelogd is, dan is het aantal affected rows dus 0, terwijl het eindresultaat precies is wat ik wil bereiken. Ik wil dan ook geen error krijgen in dat geval.

Wat dat betreft lijkt jouw idee van hoe het zou moeten werken dus niet helemaal wenselijk. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 07-04 22:27

Bosmonster

*zucht*

? is een string, dus de query is syntactisch nu toch gewoon niet goed?

  • Reinder83
  • Registratie: September 2002
  • Laatst online: 27-03 10:13
Bosmonster schreef op dinsdag 21 februari 2006 @ 10:00:
? is een string, dus de query is syntactisch nu toch gewoon niet goed?
Het gaat hier om een prepared statement ;)

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 07-04 22:27

Bosmonster

*zucht*

Reinder83 schreef op dinsdag 21 februari 2006 @ 10:08:
[...]

Het gaat hier om een prepared statement ;)
Ah, te snel gelezen (en misschien eens wat meer in PHP5 duiken :P)

Dan zie ik zoals -nme- al zegt weinig fouts, behalve dat er misschien geen rows aangedaan worden, wat uiteraard geen sql fout oplevert (gelukkig maar)..

[ Voor 8% gewijzigd door Bosmonster op 21-02-2006 10:36 ]


  • Explore
  • Registratie: Maart 2001
  • Laatst online: 08-04-2011

Explore

Op zoek naar werk

Topicstarter
hm ja, jullie hebben gelijk natuurlijk. ('t was laat! :) )

maar zoals nme al zegt, hoe kan je nou 't verschil zien tussen een execute waar mykey niet bestaat (0 affacted) of wel mykey wel bestaat, maar myfield al 1 is (0 affected)?

[ specs ] [ Tweaker gallery ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 11-03 14:33

NMe

Quia Ego Sic Dico.

In jouw voorbeeld heb je maar één veld in je WHERE staan, dus wanneer er geen affected rows zijn, dan komt dat altijd omdat er geen records zijn met die ene waarde. Om te kijken of mykey niet bestaat kun je vantevoren een aparte select-query doen, veel meer dan dat zit er denk ik niet op.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 07-04 22:27

Bosmonster

*zucht*

-NMe- schreef op dinsdag 21 februari 2006 @ 19:53:
In jouw voorbeeld heb je maar één veld in je WHERE staan, dus wanneer er geen affected rows zijn, dan komt dat altijd omdat er geen records zijn met die ene waarde.
Das niet altijd waar. Als er geen wijzigingen plaatsvinden in de update (waarden die je update zijn gelijk aan die in de DB bijvoorbeeld), krijg je ook 0 affected.

  • Explore
  • Registratie: Maart 2001
  • Laatst online: 08-04-2011

Explore

Op zoek naar werk

Topicstarter
Ja, dat was dus precies ' t probleem even. Maar dat is inderdaad op te lossen met een extra select NA de update.
Als de update 'goed' gaat, dan is affected rows > 0
Als de update 'fout' gaat, dan is affected rows = 0: doe een select op mykey
Als num_rows > 0 dan bestaat mykey
Als num_rows = 0 dan bestaat mykey niet... voila!

thanks! :)

[ specs ] [ Tweaker gallery ]


  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05-2025

GX

Nee.

Kan je niet gewoon een vorm van mysql_error() gebruiken? Wanneer mysql_errno() groter is dan 0, is er iets fout; je mysql-wrappert heeft vast een soortgelijke functie.

Verwijderd

GX schreef op woensdag 22 februari 2006 @ 19:48:
Kan je niet gewoon een vorm van mysql_error() gebruiken? Wanneer mysql_errno() groter is dan 0, is er iets fout; je mysql-wrappert heeft vast een soortgelijke functie.
Ja dat kan hij doen, maar daarmee lost hij z'n probleem niet op. Het probleem is niet dat hij geen error af kan vangen, het probleem is dat er domweg geen error is.

Een simpele
code:
1
2
3
if ($stmt->rows_affected==0) { 
  throw new QueryFailedException("Record with key " . $sMyKey . " not found");
}


is voldoende om te bereiken wat hij wil, alhoewel je natuurlijk vraagtekens kunt zetten bij het throwen van een exception voor iets wat eigenlijk geen 'echte' error is.
Pagina: 1