mysql_affected_rows zählt nicht richtig :-(
Theo
- php
Hi,
bei mir kommt immer als Ergebnis "Doof, Zeile wurde nicht geändert", also wäre kein Datensatz betroffen gewesen. Egal, ob die Zeile durch das Script geändert wurde oder nicht.
Ist da ein Fehler im Code oder nicht?
Danke
Theo
--------------------------- CODE -------------------------
$result=mysql_query("update tabelle set UserAktiv="1", UserLastvisit="".$Datum."" where UserName = "$Username"");
if ($result==FALSE) {
die(mysql_error($db));
}
if (mysql_affected_rows($result) == 0) {
echo ("Doof, Zeile wurde nicht geändert");
exit;
} else {
echo ("Prima, Zeile wurde geändert");
exit;
}
------------------------------------------------------------------
Halihallo Theo
bei mir kommt immer als Ergebnis "Doof, Zeile wurde nicht geändert", also wäre kein Datensatz betroffen gewesen. Egal, ob die Zeile durch das Script geändert wurde oder nicht.
Ist da ein Fehler im Code oder nicht?
Die MySQL-API definiert ein Feld CLIENT_FOUND_ROWS, welches bei PHP
wohl per default auf "FALSE" steht. Das hat den komischen
Seiteneffekt, dass bei einem UPDATE-Statement nur jene Records
gezählt werden, die tatsächlich geändert haben, nicht jene, die auf
die WHERE-Clause "passen" (wie erwartet; bei CLIENT_FOUNT_ROWS=TRUE).
Sieh mal nach, ob PHP eine Möglichkeit bietet, dieses Attribut zu
ändern.
Viele Grüsse
Philipp
Halihallo Theo
Aus http://ch.php.net/manual/de/function.mysql-connect.php:
phpweb at eden2 dot com, schrieb als Kommentar um
28-Jun-2003 05:55 :
<cite>
client_flags can be things other than MYSQL_CLIENT_COMPRESS, MYSQL_CLIENT_IGNORE_SPACE and MYSQL_CLIENT_INTERACTIVE.
I presume that mysql_connect() just passes through to the C MySQL API, which provides these constants:
#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
#define CLIENT_LONG_FLAG 4 /* Get all column flags */
#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */
#define CLIENT_COMPRESS 32 /* Can use compression protocol */
#define CLIENT_ODBC 64 /* Odbc client */
#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */
#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */
#define CLIENT_CHANGE_USER 512 /* Support the mysql_change_user() */
#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */
#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
Not all of these may work or be meaningful, but CLIENT_FOUND_ROWS
does, at least.
</cite>
Also: Bei mysql_(p)connect als [client_flags] einfach die "2"
übergeben. Scheint bei dem genannten Autor funktioniert zu haben...
Viele Grüsse
Philipp
Moin!
Also: Bei mysql_(p)connect als [client_flags] einfach die "2"
übergeben. Scheint bei dem genannten Autor funktioniert zu haben...
Ja, geht aber erst ab (IIRC) PHP Version 4.3.0. Wer das Pech hat, noch mit einer 4.2er oder älter zu arbeiten, und das nicht updaten kann, der hat Pech. Oder behilft sich damit, ein TIMESTAMP-Feld in die Tabelle zu packen und im UPDATE mit "NOW()" oder "NULL" zu füllen. Dann ändert sich immer was, und die Angabe ist wieder korrekt.
Been there, done that, have the t-shirt. ;)
- Sven Rautenberg
Halihallo Sven und Theo
Also: Bei mysql_(p)connect als [client_flags] einfach die "2"
übergeben. Scheint bei dem genannten Autor funktioniert zu haben...Ja, geht aber erst ab (IIRC) PHP Version 4.3.0. Wer das Pech hat, noch mit einer 4.2er oder älter zu arbeiten, und das nicht updaten kann, der hat Pech. Oder behilft sich damit, ein TIMESTAMP-Feld in die Tabelle zu packen und im UPDATE mit "NOW()" oder "NULL" zu füllen. Dann ändert sich immer was, und die Angabe ist wieder korrekt.
Jup. Wobei ich die Funktionalität nicht durch ein neues Attribut
gewährleisten würde (etwas viel Overhead); zugegeben, es ist die
einfachste und leider auch performanteste Lösung für alte PHP-
Versionen.
Dass CLIENT_FOUNT_ROWS per default "deaktiviert" ist, halte ich für
sinnvoll. Ein SELECT-Statement liefert für mysql_affected_rows genau
die Anzahl an Tupel, die auf die WHERE-Klause passen. Das macht
natürlich Sinn, denn genau diese sind die "Betroffenen Datensätze".
Was sind nun die "Betroffenen Datensätze" bei einem UPDATE? - Das
sind eben *nicht* jene, die auf WHERE "passen", sondern die, auf
die eine Aktion (UPDATE) ausgeführt wurde.
@Theo: Um trotz nichtgesetztem CLIENT_FOUND_ROWS an die "passenden"
(selektierten => SELECT) Tupel ranzukommen kannst du a) den Vorschlag
von Sven verfolgen, oder b) einfach einen SELECT vorschieben und dort
affected_rows auslesen. Dies braucht zwar Performance (zwei Queries),
ist jedoch (fast) "sauber". "Fast" deshalb, da du erst bei einem
TABLE LOCK sicherstellen kannst, dass sich zwischen den beiden
Queries nichts geändert hat.
Dann hättest du mehrere Informationen:
a) die passenden Einträge (SELECT's affected rows)
b) die geänderten Einträge (UPDATE's affected rows)
c) die gleich gebliebenen Einträge (Differenz der beiden obigen),
die trotz UPDATE auf status quo blieben.
WICHTIG: Wie du siehst, ist affected_rows kein Beweis für die
korrekte Verarbeitung des Befehls. Falls du damit eine
Fehlerbehandlung implementieren möchtest, verwende (um Himmels
Willen) folgendes Konstrukt:
mysql_query(...) || die(mysql_error());
http://www.php.net/mysql_error
oder über Abfrage von
http://www.php.net/mysql_errno
so much for old PHP versions...
Viele Grüsse
Philipp