TO_DAYS und FROM_DAYS in PHP

Ich war gerade mal so frei, eine einfache Implementierung der beiden MySQL-Funktionen TO_DAYS und FROM_DAYS in PHP zu basteln. Die Funktionen sind weder vollständig noch sonderlich elegant programmiert, aber sie sind mit den Werten aus MySQL kompatibel, d.h. man kann aus den Zahlen, die MySQL liefert in PHP ein Datum erstellen – und umgekehrt.

Sie funktionieren für’s hier und jetzt. Wer also in der 32bit Unix-Zeit bleibt, der sollte auf der sicheren Seite sein.

function TO_DAYS($date) {
	if (is_numeric($date)) {
		$res = 719528 + (int) ($date / 86400);
	} else {
		$TZ = date_default_timezone_get();
		date_default_timezone_set('UTC');
		$res = 719528 + (int) (strtotime($date) / 86400);
		date_default_timezone_set($TZ);
	}
	return $res;
}

function FROM_DAYS($daystamp) {
	return gmdate('Y-m-d', ($daystamp - 719528) * 86400);
}

MySQL unter Linux einrichten – Wie fange ich an?

MySQL ist eine der in Open Source Welt sehr verbreitete Datenbank. Teilweise liegt das sicher auch daran, dass sie unter diversen Linux-Distributionen sehr einfach zu installieren ist oder sogar direkt mit installiert wird.

Nach dem Installieren steht man dann aber mit einem tollen, laufenden Daemon da. Wie fängt man an?

  • Wie setzt man das Passwort für den Datenbank-Admin „root“?
  • Wie greift man auf den Datenbank-Dienst zu?
  • Wie legt man eine neue Datenbank an?
  • Wie legt man neue User an?
  • Wie setzt man Berechtigungen für diese User?

Das steht eigentlich alles auch in der Dokumentation drin – aber dummerweise in Form einer Befehls-Referenz, so dass man eigentlich schon wissen oder ahnen muss, wonach man genau sucht, um auch fündig zu werden.

Also – wie fängt man an?

Diese Beschreibung gilt für eine frische Installation unter Debian Linux, wird sich aber bei anderen Linux-Distributionen vermutlich nur in Details unterscheiden.

Schritt 1: Ein Passwort für den Datenbank-Admin „root“

Nach der Installation mit apt-get oder aptitude hat der Datenbank-Admin noch kein Passwort. Das sollte man schnellstens ändern, indem man an der Shell das Tool „mysqladmin“ aufruft:

# mysqladmin -u root password [NEUES-PASSWORT]

Schritt 2: Einloggen auf der Datenbank

Zum Zugriff auf der Datenbank gibt es das Client Programm „mysql„. Als Parameter übergibt man diesem den Usernamen und die Information, dass man sich mit einem Passwort einloggen möchte. Wenn man auf eine bestimmte Datenbank auf dem Server zugreifen möchte, so gibt man auch deren Namen als Parameter mit.

# mysql -u root -p

Nach dem Einloggen sieht das ganze eigentlich nicht viel anders aus als eine ganz normale Shell. Auf den ersten Blick wirkt nur vielleicht der Eingabeprompt etwas befremdlich („mysql>“). An dieser Stelle werden jetzt aber SQL-Befehle an den DB-Server übergeben. Die Befehle müssen jeweils mit einem Semikolon „;“ abgeschlossen werden. Wenn man nur Return drückt, so kann man den SQL-Befehl auf mehrere Zeilen weiterschreiben, bis eben ein Semikolon kommt.

Schritt 3: Das Anlegen einer neuen Datenbank

Eine neue Datenbank legt man an, indem man sich mittels „mysql“ in die Datenbank einloggt und dann den SQL-Befehl „CREATE DATABASE“ verwendet.

(Man kann auch über „mysqladmin“ eine neue Datenbank anlegen. Ich bevorzuge aber den Weg über den SQL-Befehl.)

mysql> CREATE DATABASE neuedatenbank;

CREATE DATABASE kann noch einen Haufen weitere Parameter annehmen (Beispielsweise die Zeichencodierung). Diese sind in der Dokumentation zu finden.

Schritt 4: Das Anlegen eines neuen Datenbank-Users

User legt man konsequenterweise mit dem ähnlich klingenden Befehl „CREATE USER“ an:

mysql> CREATE USER neueruser@localhost
IDENTIFIED BY 'neuespasswort';

Schritt 5: Zugriffsberechtigungen in MySQL setzen

Danach muss man dem User noch Rechte auf die Datenbank geben. Das geht mit dem Befehl „GRANT„:

mysql> GRANT ALL ON neuedatenbank.* TO neueruser@localhost;

Damit hat der User ALLE Rechte auf der entsprechenden Datenbank. Alternativ kann man ihm auch beispielsweise nur SELECT und INSERT („SELECT, INSERT“ statt „ALL“) oder auch nur Zugriff auf eine bestimmte Tabelle erlauben („neuedatenbank.tabelle“ statt „neuedatenbank.*“)

Danach ist es sinnvoll erst mal den Befehl „FLUSH PRIVILEGES;“ abzufeuern, damit auch sichergestellt wird, dass die neu angelegten Zugriffsberechtigungen auch auf jeden Fall gelesen werden.

Schritt 6: Tools zur Administration

Zum Loslegen ist das erst mal genug. Ich würde danach möglichst schnell auf ein Admin-Werkzeug wie beispielsweise phpMyAdmin (PHP-basierte Weboberfläche) oder HeidiSQL (Windows) umsatteln, weil die Bedienung über die Konsole etwas mühselig ist.

Wenn man von Extern auf die Datenbank zugreifen will (beispielsweise über den Windows Client HeidiSQL), so muss man die Datenbank auf eine externe IP lauschen lassen. Das stellt man in der MySQL-Konfiguration my.cnf ein. Für „Produktivsysteme“ würde ich aus Sicherheitsgründen davon aber abraten, so lange diese IP für jeden aus dem Internet zugänglich ist. Für Entwicklungs-Systeme im hausinternen Netzwerk gilt diese Einschränkung natürlich nicht.

Ausserdem muss natürlich auch ein User existieren, der sich von extern einloggen kann. User neueruser@localhost könnte das nicht, da er ja dann nicht von localhost käme.

GROUP_CONCAT()

Als Programmierer lernt man nie aus… Es gibt immer noch die eine Funktion, die das Arbeiten einfacher macht…

Heute bin ich über die Funktion GROUP_CONCAT() in MySQL gestolpert.

Eine ganz einfache Funktion – an sich wenig beeindruckend und alles andere als komplex. Nur: Ich hab sie bisher noch nicht gekannt. Im „allgemeinen SQL“ existiert sie nicht, und auch bei Microsoft Transact-SQL konnte ich kein Äquivalent finden. Ich dachte mir immer „Wäre schön, wenn so was existieren würde“ – aber nachgeschaut habe ich nie…

Was tut sie?

Wenn man einen SQL-Query mit einem GROUP BY einsetzt, dann kann man mit GROUP_CONCAT() alle Strings einer Spalte einfach konkatinieren, also hintereinander hängen. Auf Wunsch mit Trennzeichen.

Nehmen wir einfach mal an, wir haben eine Tabelle mit Blog-Einträgen und eine weitere Tabelle, in der die ganzen Tags zu diesen Blogeinträgen stehen – ein Tag pro Datensatz:

Blog_Posts:

Post_ID Title
1 Wetter
2 Leben
3 Sex
4 Weltfrieden
Blog_Tags:

Post_ID Tag
1 sonne
1 wolken
3 oben ohne
3 frau

Jetzt wollen wir die Blogbeiträge incl. allen Tags auslesen. Wir haben drei Möglichkeiten:

  • Wir lesen erst Blog_Posts und machen dann einen weiteren SELECT auf Blog_Tags – einen für jeden Blog-Eintrag. Dadurch fragen wir die beiden Tabellen oben nacheinander ab, erhalten also zwei Result-Sets, die wir mittels Programm zusammenführen müssen.
  • Wir lassen SQL einen JOIN auf beide Tabellen ausführen und sortieren dann mittels Programm die Daten aus. Als Ergebnis bekommen wir beispielsweise…
    SELECT P.Post_ID, P.Title, P.Tag
    FROM Blog_Posts P
    JOIN Blog_Tags T ON P.Post_ID = T.Post_ID
    WHERE P.Post_ID = 1
    Post_ID Title Tag
    1 Wetter sonne
    1 Wetter wolken

    Wir müssen also auswerten, dass die beiden Zeilen zusammengehören und nur deshalb so erscheinen, weil mehrere Tags vorliegen.

  • Wir setzen GROUP_CONCAT() ein, und lassen MySQL die Arbeit übernehmen.
    SELECT P.Post_ID, P.Title,
           GROUP_CONCAT(T.Tag SEPARATOR ', ') AS Tags
    FROM Blog_Posts P
    JOIN Blog_Tags T ON P.Post_ID = T.Post_ID
    WHERE P.Post_ID = 1
    GROUP BY P.Post_ID, P.Title
    Post_ID Title Tags
    1 Wetter sonne, wolken