Dieser Post wurde aus meiner alten WordPress-Installation importiert. Sollte es Darstellungsprobleme, falsche Links oder fehlende Bilder geben, bitte einfach hier einen Kommentar hinterlassen. Danke.
mySQL macht selten was man erwartet, einige Sonderfälle scheinen absolut willkürlich zu sein. Dazu gehört die Verwendung von NOW() oder CURRENT_TIMESTAMP in DEFAULT-Werten einer Tabelle.
Zunächst einmal benötigen temporäre Tabellen (die ohnehin die aktuelle Verbindung nicht überdauern) zwangsweise eine Datenbank:
mysql> CREATE TEMPORARY TABLE test (`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(`id`));ERROR 1046 (3D000): No database selectedDas mag zwar zunächst sinnvoll erscheinen - schließlich ist eine Tabelle ohne Datenbank nicht möglich - auf den zweiten Blick stellt sich allerdings die Frage, warum diese Einschränkung auch für temporäre Tabellen gilt. Wenn mySQL eine Datenbank benötigt, kann es doch einfach eine erstellen, zumal explizit temporäre Datenbanken auch nicht unterstützt werden:
mysql> CREATE TEMPORARY DATABASE tempdb;ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DATABASE tempdb' at line 1Nun aber zum eigentlichen Thema dieses Posts. Gegeben sei eine Tabelle mit einer TIMESTAMP-Spalte und dem Zusatz "ON UPDATE CURRENT_TIMESTAMP", alternativ auch NOW(). Das Beispiel - und so bin ich überhaupt erst auf das oben genannte Problem gestoßen - funktioniert selbstverständlich auch mit einer temporären Tabelle.
mysql> CREATE TABLE test (`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `updated` TIMESTAMP NOT NULL ON UPDATE NOW(), `x` INTEGER, PRIMARY KEY(`id`));Query OK, 0 rows affected (0.06 sec)Die Tabelle enthält also drei Datensätze und die Spalte updated wurde - mangels expliziter DEFAULT-Angabe im CREATE TABLE - mit dem mySQL-Datumsäquivalent einer leeren Zelle initialisiert. Soweit nichts Besonderes - bis die entsprechenden Zeilen aktualisiert werden:mysql> INSERT INTO test() VALUES();Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO test() VALUES();Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO test() VALUES();Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM test;+----+--------------------+------+| id | updated | x |+----+--------------------+------+| 1 | 0000-00-00 00:00:00 | NULL || 2 | 0000-00-00 00:00:00 | NULL || 3 | 0000-00-00 00:00:00 | NULL |+----+--------------------+------+3 rows in set (0.00 sec)
mysql> UPDATE test SET x=1;Query OK, 3 rows affected (0.00 sec)Rows matched: 3 Changed: 3 Warnings: 0Der ersten UPDATE-Befehl setzt in allen Zeilen einen Wert für die Spalte x und der zweite UPDATE ändert die erste Zeile. Der letzte UPDATE-Befehl soll eigentlich die zweite Zeile ändern, übergibt allerdings den gleichen Wert für x, der sich bereits in der Tabelle befindet. MySQL bestätigt dies auch durch Rows matched: 1 Changed: 0.mysql> UPDATE test SET x=2 WHERE id=1;Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0
mysql> UPDATE test SET x=1 WHERE id=2;Query OK, 0 rows affected (0.00 sec)Rows matched: 1 Changed: 0 Warnings: 0
mysql> SELECT * FROM test;+----+---------------------+---+| id | updated | x |+----+---------------------+---+| 1 | 2012-02-13 12:29:40 | 2 || 2 | 2012-02-13 12:29:30 | 1 || 3 | 2012-02-13 12:29:30 | 1 |+----+---------------------+---+3 rows in set (0.00 sec)
MySQL versteht das ON UPDATE CURRENT TIMESTAMP nicht etwa als "aktualisiere diese Spalte bei jedem UPDATE-Befehl der diese Zeile betrifft", sondern vielmehr als "aktualisiere diese Spalte bei jedem UPDATE-Befehl, der diese Spalte tatsächlich ändert". Es reicht demnach nicht aus, eine Tabellenzeile mittels UPDATE modifizieren zu wollen, mindestens eine der Spalten dieser Zeile muss auch tatsächlich einen neuen Wert erhalten. Die Alternativ wäre ein explizites UPDATE test SET updated=NOW() WHERE id=? um den - eigentlich automatisch aktualisierten - Änderungszeitpunkt zwangsweise neu zu setzen.
1 Kommentar. Schreib was dazu-
MeMyselfAndI
26.06.2013 18:47
Antworten
Der Grund für die Pflicht einer Datenbank ist recht simpel.
mySQL speichert die Datenbank als Pfad lokal im Dateisystem. Alleine schon um das Überlaufen bestimmter Mointpoints zu verhindern kann es sinnvoll sein die Datenverzeichnisse z.B. per symbolischen Links aufzuteilen. Nicht jede DB muss auch zwingend im mySQL Subdir liegen.