Vorwort
Diese "Referenz" zeigt nur die allerwichtigsten MYSQL-Befehle. Für eine
ausführlichere Referenz empfehle ich die
PHP-Referenz.
Viele dieser Befehle sind ähnlich den
ODBC-Befehlen aufgebaut. Durch Ersetzen
des MYSQL_ durch ODBC_ erreicht man die ODBC-Befehle.
Dabei verliert man jedoch auch viel Performance und z.B. unter Linux ist ODBC
sowieso ein Sorgenkind.
MYSQL_CONNECT(...)

|
int mysql_connect(string host, string [user], string [password]); |
Ist Voraussetzung in jedem PHP-Programm, das MySQL benutzen will. Wenn kein
Benutzername und Passwort angegeben werden, wird mit dem aktuell angemeldeten
Benutzernamen und Passwort verbunden; was üblicherweise sogar funktioniert.
Als Hostnamen können Sie getrost auch auf entfernten Systemen
"localhost" verwenden, da die Dateien ja (üblicherweise) jeweils auf dem System gespeichert
werden, auf dem sich auch die Datenbank befindet.
Mit MySQL_Connect wird meist auch gleich die Datenbank der Wahl ausgewählt; dies geht mit
mysql_select_db(...)
und ist deshalb hier gleich mit-erwähnt.
mysql_connect('localhost') OR DIE ("Konnte nicht mit MySQL verbinden.");
@mysql_select_db("datenbankname") OR DIE ("Konnte nicht mit Datenbank auf MySQL verbinden.");
Hinweis: OR DIE (String)
lässt den Programmablauf mit der Meldung String abbrechen
falls das Ergebnis der vorangegangenen Operation false war. Der Klammeraffe @ vor dem
mysql_select_db verhindert eine Fehlerausgabe (die wird mit OR DIE behandelt).
MYSQL_CLOSE()
Schließt die Verbindung zu MySQL und ist am Ende jedes Programmes, das auch MYSQL_CONNECT
benutzt hat, aufzurufen.
mysql_close();
MYSQL_QUERY(...)

|
int MYSQL_QUERY(string query_string); |
führt eine SQL-Anweisung aus. Zurückgeliefert wird false für fehlerhafte Ausführung und ansonsten
eine Identifikation des Ergebnisses.
mysql_query ("insert into kueche values ('Messer')");
MYSQL_DB_QUERY(...)

|
int MYSQL_DB_QUERY(String Datenbank, String query_string); |
führt eine SQL-Anweisung auf Datenbank aus. Im Unterschied zu
MYSQL_QUERY
erwartet es jedoch mehrere Ergebnisse: Denn eine Abfrage der Einzelergebnisse wie
durch ODBC_RESULT ist
in MySQL vermutlich aus Performancegründen tatsächlich nur in ODBC vorgesehen.
(ODBC_RESULT muss, um eine komplette Tabelle auszugeben, für jede Spalte eine
Ergebnisabfrage starten, MYSQL_FETCH_ARRAY nur für jede Zeile).
Zurückgeliefert wird false für fehlerhafte Ausführung und ansonsten
eine Identifikation des Ergebnisses.
$result=mysql_db_query ("testdb","select * from kueche");
while ($row=mysql_fetch_object($result))
{
$geraet=$row->kuechengeraet;
echo "$geraet ";
}
mysql_free_result($result);
MYSQL_FREE_RESULT(...)

|
int MYSQL_FREE_RESULT(int result_id); |
gibt den Speicherbereich
wieder frei, den MYSQL_DB_QUERY eingenommen hat (und ist nach dem
Abfragen der gewünschten Zeilen durch MYSQL_FETCH_OBJECT auch empfohlen).
siehe MYSQL_DB_QUERY-Beispiel.
MYSQL_FETCH_ARRAY(...)

|
array mysql_fetch_array(int result_id); |
Lädt in der Form
array mysql_fetch_object(int result_id);
die
nächste Zeile des MYSQL_DB_QUERY in ein Array und liefert true zurück,
falls es eine gibt. Das zurückgegebene Array ist i.d.R.
assoziativ (es gibt einen weiteren Parameter,
der den Typ angibt; dieser Parameter wird allerdings selten genug benötigt um ihn hier nicht zu
erwähnen ;)),
d.h., ich kann durch Ansprechen von $arrayname->Spaltenname die entsprechenden Spalten auslesen.
Der Spaltenname darf dabei nicht in Hochkommas stehen, da es sich bei den Teilen des Arrays
um Variablen handelt, die nun mal die gleichen Namen wie die Spalten in der Datenbank bekommen.
siehe MYSQL_DB_QUERY-Beispiel.
MYSQL_RESULT(...)

|
string mysql_result(int result_id, int row, int column); |
Um mehrere Spalte zurückgeliefert zu bekommen ist MYSQL_RESULT aus
Performancegründen zum wegschmeißen, verwenden Sie lieber
mysql_fetch_object(...) nach
einem mysql_db_query(...).
$result=mysql_query("select MAX(id) FROM mydatabase");
$id=mysql_result($result,0,0);
Hinweis: Achten Sie darauf, nie ein Leerzeichen zwischen arithmetischen Funktionen
wie MAX, MIN oder AVG und dem Spaltennamen einzufügen.
MYSQL_NUM_ROWS(...)

|
int mysql_num_rows(int result_id); |
Liefert die Anzahl der Zeilen im Ergebnis zurück. Nützlich z.B.
bei MYSQL_DB_QUERYs mit einer Where-Bedingung oder eben um die Anzahl der
Datenbankeintragungen zu wissen.
mysql_connect('localhost') OR DIE ("Konnte nicht mit MySQL verbinden.");
@mysql_select_db("testdb") OR DIE ("Konnte nicht mit Datenbank auf MySQL verbinden.");
mysql_query ("drop table kueche"); // da machen wir kein OR DIE dahinter weil die Anwendung
// sonst immer stirbt wenn es kueche noch nicht gab
mysql_query ("create table kueche (kuechengeraet varchar(100))") OR DIE ("invalid request at l2");
mysql_query ("insert into kueche values ('Messer')") OR DIE ("invalid request at l3");
mysql_query ("insert into kueche values ('Gabel')") OR DIE ("invalid request at l4");
mysql_query ("insert into kueche values ('Löffel')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Mixer')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Kochlöffel')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Teelöffel')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Besteck')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Teller')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Toaster')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Tassen')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Sieb')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Topflappen')") OR DIE ("invalid request");
mysql_query ("insert into kueche values ('Topfdeckel')") OR DIE ("invalid request");
$res=mysql_db_query ("testdb","select * from kueche");
$zeile=mysql_num_rows($res)-10;
if ($zeile<0) $zeile=0;
mysql_data_seek($res,$zeile);
while ($row=mysql_fetch_object($res))
{
$geraet=$row->kuechengeraet;
echo "$geraet";
}
mysql_free_result($res);
mysql_close();
(obiges Beispiel gibt die 10 letzten Küchengeräte aus ;))
MYSQL_DATA_SEEK(...)

|
int MYSQL_DATA_SEEK(int result, int row) |
Offensichtlich akzeptiert MYSQL_FETCH_OBJECT keine Angabe,
welche
Zeile gelesen werden soll -- es ist immer die nächste. Um etwaige
Versuche vorwegzunehmen: Auch MYSQL_FETCH_ROW und MYSQL_FETCH_ARRAY
nehmen keine solchen Parameter an -- es ist trotzdem möglich.
int MYSQL_DATA_SEEK(int result, int row)
veranlasst MySQL angegebene Zeile als nächstes Ergebnis (z.B. auf
eine MYSQL_FETCH_OBJECT-Anfrage) zurückzuliefern. Die jeweils nächste
Abfrage wird dann wieder die jeweils nächste Zeile zurückliefern.
Row beginnt bei 0.
Rückgabe: true bei Erfolg, false bei Misserfolg.
siehe MYSQL_NUM_ROWS-Beispiel.
Transaktionen unter MySQL
Datenbanken bieten mit sogenannten Transaktionen die Möglichkeit,
mehrere SQL-Anweisungen in einen Block zu kapseln und diesen Block dann
"sicher" auszuführen. Sicher bedeutet in diesem Zusammenhang z.B.,
- dass die Ausführung des gesamten Blocks garantiert wird, der Block
kann nicht durch die Anfragen anderer Benutzer beeinflusst werden.
Beispiel:
insert into tabellemitautoincrement values ('Daten');
select MAX(ID) from tabellemitautoincrement;
liefert ohne Transaktion unter Umständen nicht die ID des
gerade eingefügten Datensatzes zurück. Nämlich genau dann nicht, wenn
gleichzeitig mehrere Benutzer diesen Befehl ausführen und die Datenbank
dann (von uns unbemerkt) Folgendes ausführt
insert into tabellemitautoincrement values ('Daten'); // unser User
insert into tabellemitautoincrement values ('fremde Daten'); // wird jetzt von uns
// unbemerkt von einem Dritten (für uns nicht sichtbar im Hintergrund) ausgeführt
select MAX(ID) from tabellemitautoincrement; // liefert jetzt die ID des Dritten,
// nicht unsere
In dem Fall bekommen wir die ID des fremden Zugriffs.
Sowas kommt bei großen Datenbanken häufig genug vor,
und kann unglaubliche Probleme verursachen und
-
dass ein Eintrag garantiert zu Ende ausgeführt wird, oder
komplett Rückgängig gemacht wird. Es kann Situationen geben,
in der die Datenbank mitten im Anweisungsblock merkt, dass
einige Anweisungen nicht ausgeführt werden können oder dürfen (z.B.
gibt es Regeln die das verbieten). Wenn Sie in Ihrer Datenbank
Rechte verwalten, die nur bei jeweils ein Objekt betreffen dürfen,
können solche Regeln zum Beispiel dazu führen, dass das Recht einem
Objekt entzogen, aber einem anderen nicht zugeordnet werden kann.
Die Literatur nennt hier gerne den Transfer von Geld von einem
Konto zu einem anderen: Zuerst muss dem ersten Konto Geld abgezogen
werden, um es dann dem Zweiten zu geben. Zieht jemand den Stecker
auf einer Maschine, die das 10 Millionen mal in der Sekunde macht,
besteht eine gewisse Wahrscheinlichkeit, dass einige Leute Geld
schon abgezogen, andere jedoch noch nicht zugerechnet bekommen
haben. Das ist auch der Grund, warum Banken so reich sind.
Um das zu vermeiden, haben Datenbankentwickler einen Mechanismus
implementiert, der protokolliert, welche Befehle schon
ausgeführt wurden, und diese Rückgängig machen kann, wenn
zum Beispiel bei einem Befehl ein Regelverstoß vorliegt - oder
wenn die Datenbank neu hoch gefahren wird und einige Transaktionen
waren noch nicht abgeschlossen.
Je anspruchsvoller die Aufgabe, desto eher empfiehlt sich eine Datenbank
statt einer Datei. Nehmen wir die o.g. Überweisungsvorgänge
im Bankenbereich:
Da wird ein Betrag von einem Konto abgezogen und auf ein anderes gutgeschrieben.
Dieser Vorgang muss atomar geschehen, das heißt, ganz oder garnicht.
Wird nach einer Gutschrift festgestellt, dass der Überweisende garnicht genug
Geld auf seinem Konto hat, wird der gesamte Vorgang rückabgewickelt.
Das unterstützen Datenbanken, indem sie die Möglichkeit bieten, mehrere Vorgänge
zu sogenannten
Transaktionen zusammen zu fassen. Der Programmierer muss sich
dann nicht mehr um die Rückabwicklung jedes einzelnen Vorganges kümmern, sondern nur noch
entscheiden, ob die gesamte Transaktion durchgeführt (ganz) oder rückabgewickelt
(garnicht ausgeführt) wird.
Bei Interesse können Sie mal im Internet nach dem
ACID-Prinzip für Datenbanken suchen.
Das Behandeln von Transaktionen
unter MySQL ist sehr elegant gelöst. Vor Transaktionsbeginn
wird dem Datenbanksystem der SQL-Befehl
begin übergeben,
nach Ende
commit zur Ausführung oder
rollback zum Verwerfen.
Man benötigt transaktionssichere Tabellentypen wie InnoDB oder BDB, dazu wiederum benötigt man
die Max-Version von MySQL. Zur Erstellung von transaktionssicheren Tabellen siehe
die MySQL-Referenz (
www.mysql.com/doc/en/Table_types.html).
// Dieses Beispiel führt eine Überweisung über 100 Euro von Konto 3301 auf Konto 3302 durch.
// Wenn 3301 zu wenig Geld hat, wird nichts durchgeführt.
// ...
mysql_connect("localhost") OR DIE("Konnte nicht mit localhost verbinden.");
mysql_select_db("test") OR DIE("Konnte Datenbank nicht finden.");
function echoBalance()
{
mysql_query('begin');
$res=mysql_query('select * from konto');
mysql_query('commit');
echo "<br>";
while ($row=mysql_fetch_array($res))
{
echo "Konto ".$row["kontonummer"]." hat ".$row["kontostand"]."Euro <br>";
}
}
mysql_query('drop table if exists konto');
mysql_query('create table konto (kontonummer varchar(5), kontostand float) type=InnoDB');
mysql_query('insert into konto (koconnect("localhost") OR DIE("Konnte nicht mit localhost verbinden.");
mysql_select_db("test") OR DIE("Konnte Datenbank nicht finden.");
function echoBalance()
{
mysql_query('begin');
$res=mysql_query('select * from konto');
mysql_query('commit');
echo "<br>";
while ($row=mysql_fetch_array($res))
{
echo "Konto ".$row["kontonummer"]." hat ".$row["kontostand"]."Euro; <br>";
}
}
mysql_query('drop table if exists konto');
mysql_query('create table konto (kontonummer varchar(5), kontostand float) type=InnoDB');
mysql_query('insert into konto (kontonummer, kontostand) values (3301, 120.70)');
mysql_query('insert into konto (kontonummer, kontostand) values (3302, 11)');
echo "Vor der ersten Transaktion";
echoBalance();
mysql_query('begin');
mysql_query('update konto set kontostand=kontostand-100 where kontonummer=3301');
mysql_query('update konto set kontostand=kontostand+100 where kontonummer=3302');
$res=mysql_query('select kontostand from konto');
$kontostand=mysql_result($res,0,0);
if ($kontostand<0)
{mysql_query('rollback');}
else
{mysql_query('commit');}
echo "Nach der ersten Transaktion";
echoBalance();
mysql_query('begin'); // Die gleiche Transaktion nochmal
mysql_query('update konto set kontostand=kontostand-100 where kontonummer=3301');
mysql_query('update konto set kontostand=kontostand+100 where kontonummer=3302');
$res=mysql_query('select kontostand from konto');
$kontostand=mysql_result($res,0,0);
if ($kontostand<0)
{mysql_query('rollback');}
else
{mysql_query('commit');}
echo "Nach der zweiten, hoffentlich fehlgeschlagenen Transaktion";
echoBalance();
// ...
zu beachten ist, dass man innerhalb der Transaktion mit select bereits einen Stand lesen kann,
den man nur logisch (also ohne Commit auszulösen) geschrieben hat.