Author: Progman, zuletzt bearbeitet von tittenmaus @ 2004/11/28 14:35:32
Bitte beachten Sie, dass die Tutorialkapitel zusammenhängen. Wenn sie direkt auf ein Kapitel verlinkt wurden müssen Sie gegebenenfalls die vorherigen Kapitel auch lesen. Achten Sie beim lesen darauf, dass Sie kein Kapitel überspringen.
MySQL Querys richtig einrücken
- Warum einrücken?
- Schlüsselwörter groß schreiben
- Schlüsselwörter in MySQL
- SELECT-Befehl einrücken
- UPDATE-Befehl einrücken
- DELETE-Befehl einrücken
- INSERT-Befehl einrücken
- MySQL-Querys mit einem Semikolon abschließen
- SELECT *
- MySQL-Querys in PHP
1. Warum einrücken?
Diese Kapitel habe ich nun hier reingeschrieben, damit ich den Leuten in #php und #php.de helfen kann. Denn was da manchmal für MySQL-Querys gesendet wird ist unter aller sau...
Es kann vorkommen, dass ihr einen MySQL-Query sendet und dieser einen Fehler liefert. Dieser Fehler ist nicht unbedingt sofort einsichtig, warum er da ist. Spätestens bei der Fehlermeldung MySQL Error: You have an error near '' at Line 1 steht man auf dem Schlauch. Man kann nicht erkennen, wo jetzt der Fehler ist.
Beim Formartieren des MySQL-Querys ändert sich bei einem Fehler die Zeilenangabe. Dann steht da z.B. ... at Line 5 und könnt da nach eurem Fehler suchen. In PHP rückt ihr ja euren PHP-Code auch ein (hoffe ich zumindest). Ihr schreibt ja nicht den PHP-Code in einer einzigen Zeile, was natürlich möglich wäre. Doch dann habt ihr das selbe Problem wie in MySQL, wenn ein Fehler auftritt. Parse Error: unexcepted T_VARIABLE, excepted T_DOT or T_SEMIKOLON at Line 1 oder so ähnlich. Deshalb sollte man MySQL-Querys entsprechend einrücken. Der Datenbank ist es dabei egal, wenn da Whitespaces wie \n oder Leerzeichen sind.
2. Schlüsselwörter groß schreiben
Es hat sich eingebürgert, dass man Schlüsselwörter wie SELECT und WHERE groß schreibt. Man erkennt dann sofort, was der Query macht, da man sofort zwischen Werten, Tabellennamen, Spaltennamen und Schlüsselwörter unterscheiden kann. Man kann es sich natürlich schwer machen und die Schlüsselwörter nicht komplett groß schreiben.
SeLEct ... FRoM ... wheRe ...;
Ich empfehle euch, Schlüsselwörter großzuschreiben.
SELECT ... FROM ... WHERE ...;
3. Schlüsselwörter in MySQL
In MySQL gibt es eine Menge von Schlüsselwörter, die man nicht als Spalten benutzen werden. Manchmal sehe ich folgenden Query in den Channels.
SELECT ID,Name,Email,Alter,ICQ FROM users WHERE ID=5;
Wenn ihr diesen Query absendet, werdet ihr diese oder eine so ähnlich Fehlermeldung erhalten.
MySQL Error: You have an error near 'Alter, ICQ FROM' near Line 1
Wenn ihr MySQL nicht ein wenig kennt werdet ihr den Fehler nie finden. Denn in MySQL ist Alter ein Schlüsselwort. Mit dem ALTER TABLE-Befehl bearbeiten wir die Eigenschaft einer Tabelle. Bei einem SELECT-Befehl ist dieser Befehl fehl am Platz.
Eine Liste der Schlüsselwörter in MySQL, die man nicht als Spalten- und Tabellennamen benutzen darf, findet man im MySQL Manual unter 6.1.7 Is MySQL Picky About Reserved Words?
4. SELECT-Befehl einrücken
Der SELECT-Befehl kann sehr Komplex aufgebaut sein. Jedes Schlüsselwort soll dabei in einer eigenen Zeile stehen. Dadrunter und mit 4 Leerzeichen eingerückt kommen dann die Angaben zu diesem Schlüsselwort. Diese Angaben sollte man entsprechend auch einrücken und übersichtlich schreiben. Hier ein Beispiel wie sowas aussehen könnte.
SELECT foo, bar FROM tab WHERE ka = '5' AND ( punkte > '0' OR fehler < '0' ) ORDER BY Datum DESC, punkte ASC LIMIT 10,10;
Man kann sofort die jeweiligen Angaben sofort erkennen. Aus was will ich auslesen?, Nach was soll sortiert werden?, Wie lautet die Bedingung?. Welche Angaben man in einem SELECT-Befehl verwenden kann, kann man in der MySQL-Dokumentation nachlesen.
5. UPDATE-Befehl einrücken
Die Einrückung ist so ähnlich wie bei dem SELECT-Befehl. Dies könnte so aussehen.
UPDATE tab SET punkte = '0', Datum = NOW() WHERE punkte < '0' OR punkte > '1000';
6. DELETE-Befehl einrücken
Da der DELETE-Befehl nur etwa so viele Angaben hat wie der UDPATE-Befehl ist die Formartierung eines DELETE-Befehls sehr einfach.
DELETE FROM tab WHERE wir < sie;
7. INSERT-Befehl einrücken
Einen INSERT-Befehl richtig einrücken ist schwer, denn ein INSERT-Befehl kann unterschiedlich aufgebaut sein. Die meißten kennen die Form mit VALUES und sollten den Query in etwa so formartieren.
INSERT INTO news(Inhalt, Datum, Poster) VALUES ('Ein verdammt toller text', NOW(), '4');
Diesen Query kann man aber auch anders formartieren.
INSERT INTO news (Inhalt, Datum, Poster) VALUES ('Ein verdammt toller text', NOW(), '4');
Hier kann man gucken, ob man genausoviele Spalten wie Werte angegeben hat. Wenn nicht bekommt man eine Fehlermeldung wie MySQL Error: Value Columns doesn't match Table Columns.
Der INSERT Befehl kann auch mit einer SET-Angabe benutz werden, die dann wie folgt aussieht.
INSERT INTO tab SET Name = 'foo', Email = 'bar';
Hier hat man eine direkte Zuordnung von Werten und Spalten. Aber diese einfache Methode um einen neuen Datensatz hinzuzufügen habe ich nicht durchgenommen, weil man den Aufbau sonst mit einem UPDATE-Befehl verwechseln könnte. Denn INSERT-Befehle können z.B. kein WHERE oder LIMIT enthalten, UPDATE-Befehle hingegen schon. Man würde sich da leicht vertun und ggf. solche Querys zusammenreimen.
INSERT INTO users SET foo = 'bar' WHERE ID != '5';
Man dachte hier vielleicht, das man einen Datensatz hinzufügt, wenn es keinen Datensatz mit der ID 5 gibt. Sowas hab ich alles schon gesehen...
8. MySQL-Querys mit einem Semikolon abschließen
Jeder MySQL-Befehl muss mit einem Semikolon abgeschlossen werden. Anhand des Semikolons kann MySQL mehrere Querys unterscheiden. In PHP sendet man ja Query an die Datenbank mit mysql_query. Bei dieser Funktion darf man aber das Semikolon weglassen. Das liegt daran, dass mysql_query er nur ein Query ausführt, selbst wenn dieser Funktion 2 oder mehrere MySQL-Querys mit Semikolon getrennt übergeben wurden. Dies heißt jetzt nicht, dass ihr nun immer die Semikolons weglassen könnt. Ihr solltet euch daran gewöhnen, dass MySQL-Querys mit einem Semikolon abgeschlossen werden. Denn es kann mal sein, dass ihr direkt an der MySQL-Datenbank mit dem Programm mysql arbeitet. Da muss jeder Befehl mit Semikolon abgeschlossen werdet. Hättet ihr nun gelernt, dass man bei MySQL keine Semikolons braucht, so würdet ihr mit dem Programm mysql nur Probleme kriegen und euch fragen, warum der Query nicht ausgeführt wird. Ich empfehle euch daran zu denken, dass man MySQL-Querys, auch in PHP, mit einem Semikolon beendet.
9. SELECT *
Von anderen Tutorials oder Hilfeseiten kennt man den Ausdruck SELECT *. Dies sollte man in seinen Anwendungen nicht benutzen. Warum wird in der php-FAQ unter 15.14. Warum soll ich nicht SELECT * schreiben? erklärt.
10. MySQL-Querys in PHP
In PHP sollte man, wegen der Übersicht, den Query in einer extra Variablen speichern. Dabei sollte man, wie oben erklärt, den Query über mehrere Zeilen schreiben. Dabei sollte man den Query auf das erste Schlüsselwort einrücken.
<?php
$sql = "SELECT
foo,
bar,
FROM
tab;";
?>
So ist es falsch.
<?php
$sql = "SELECT
foo,
bar,
FROM
tab;";
?>
So ist es richtig. Den Query senden wir dann wie üblich mit mysql_query mit $sql als Parameter an die Datenbank ab. Der Vorteil des Zwischenspeichers ist, dass man bei einem Fehler noch den Query ausgeben kann.
<?php
$result = mysql_query($sql) OR die("'".$sql."' : ".mysql_error());
?>
In manchen Situationen will man nur bestimmte Daten auslesen. Diese werden üblicherweise von einem Benutzer mittels eines Formulares gewählt. Der Benutzer muss aber nicht das fertige Formular benutzen sondern kann sich ein eigenes Schreiben. Dies macht er mit den Ziel die Datenbank zu hacken. Und wie?
Nehmen wir an wie haben folgenden Query.
SELECT password FROM users WHERE ID = '".$_POST['ID']."';
In dem Formular würde man normalerweise die ID eingeben, z.B. 5. Doch was ist wenn man 0' OR 1 OR 'foo' = ' eingibt. Dann sieht der zusammengesetze Query so aus.
SELECT password FROM users WHERE ID = '0' OR 1 OR 'foo' = '';
Und eine OR-Verknüpfung wo eine 1 steht ist immer true/wahr. Das heißt, dass hier jeder Datensatz ausgelesen wird. Der Hacker bekommt nun von allen Usern das Password angezeigt.
Deshalb sollte man immer die Eingaben prüfen. Man kann aber auch einen anderen Trick benutzten. Die Funktion sprintf liefert einen Übergebene String, der Platzhalter hatte, wieder zurück. Der Funktion muss man dann für die Platzhalter die Werte übergeben. Dies sieht z.B. so aus.
<?php
$sql = sprintf("SELECT
foo
FROM
tab
WHERE
ID = '%u';", $_POST['ID']);
?>
Egal was in $_POST['ID'] steht, dieser Wert wird in durch den Platzhalter in einer Zahl umgewandelt. Der Benutzer kann nun nichtmehr OR Verknüpfungen hinzufügen. Es empfielt sich deshalb die Dokumentation von sprintf durchzulesen.
Fragen zum aktuellen Thema
- Warum soll ich einrücken?
-
Einrücken erleichtet das Lesen von MySQL-Querys. Man sieht sofort was zu was gehört. Zusätzlich wird bei einem Fehler die fehlerhafte Zeile mit ausgegeben. Würden wir alles in einer Zeile schreiben, so würde da "... at Line 1" stehen. Dadurch werden wir ja nicht grad schlauer.