copyright (c)  2003   useGroup
PHP

Jochen Stärk
PHP-Tutorial
Eine kleine MySQL-Referenz

nach untenVorwort
nach untenMYSQL_CONNECT(...)
nach untenMYSQL_CLOSE()
nach untenMYSQL_QUERY(...)
nach untenMYSQL_DB_QUERY(...)
nach untenMYSQL_FREE_RESULT(...)
nach untenMYSQL_FETCH_ARRAY(...)
nach untenMYSQL_RESULT(...)
nach untenMYSQL_NUM_ROWS(...)
nach untenMYSQL_DATA_SEEK(...)
nach untenTransaktionen unter MySQL

Vorwort

nach obenVorwort 

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(...)

nach obenMYSQL_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()

nach obenMYSQL_CLOSE() 

Schließt die Verbindung zu MySQL und ist am Ende jedes Programmes, das auch MYSQL_CONNECT benutzt hat, aufzurufen.

mysql_close();


MYSQL_QUERY(...)

nach obenMYSQL_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(...)

nach obenMYSQL_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(...)

nach obenMYSQL_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(...)

nach obenMYSQL_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(...)

nach obenMYSQL_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(...)

nach obenMYSQL_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(...)

nach obenMYSQL_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

nach obenTransaktionen 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.,

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.


copyright (c)  2003   useGroup