Funktionsaufrufe in MySQL
Einführendes Beispiel
Die folgende Eingabe gibt eine mehr oder weniger zufällig ausgewählte DOUBLE-Zahl zwischen 0 (einschließlich) und 1 (ausschließlich) aus.
Eingabe
SELECT RAND();
Ausgabe
+-------------------+
| RAND() |
+-------------------+
| 0.901730651875707 |
+-------------------+
Bei der Auswertung des Ausdrucks »RAND()« wird das Programm »RAND« gestartet. Dieses legt für den Aufrufausdruck »RAND()« dann einen Wert zwischen 0 und 1 fest.
Anders gesagt: Immer wenn MySQL den Wert des Ausdrucks »RAND()« erfahren will, ruft es das Programm »RAND« auf, welches den Wert dann mitteilt.
Die Schreibweise von Aufrufen
Ein Ausdruck kann mit einem Namen geschrieben werden, dem ein Paar runder Klammern »(« »)« folgt.
- Syntax eines Aufrufs »()«
Ausdruck
.------. .-. .-.
--->| Name |--->· ( ·-->· ) ·-->
'------' '-' '-'
Es handelt sich hierbei um insgesamt drei lexikalischen Einheiten: Einen Namen, eine runde Klammer auf »(« und eine runde Klammer zu »)«.
- Neue, erweiterte Syntax (vereinfacht)
Ausdruck
.----------.
---.----------->| Literal |---------------------------.---->
| '----------' |
| .----------. |
'----------->| Name |---------------------------'
| '----------' |
| .----------. .-. .-. |
'----------->| Name |--->( ( )--->( ) )---------'
| '----------' '-' '-' |
| .-. .----------. |
'--->( - )-->| Ausdruck |---------------------------'
| '-' '----------' |
| .-. .----------. |
'--->( + )-->| Ausdruck |---------------------------'
| '-' '----------' |
| .-. .----------. .-. |
'--->( ( )-->| Ausdruck |-->( ) )-------------------'
| '-' '----------' '-' |
| .----------. .-. .----------. |
'----------->| Ausdruck |-->( * )-->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |-->( / )-->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .---. .----------. |
'----------->| Ausdruck |->( DIV )->| Ausdruck |----'
| '----------' '---' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |-->( + )-->| Ausdruck |----'
| '----------' '-' '----------' |
| .----------. .-. .----------. |
'----------->| Ausdruck |-->( - )-->| Ausdruck |----'
'----------' '-' '----------'
Im Falle dieser hier neu vorgestellten Schreibweise nennen wir die runden Klammern auch Aufrufklammern und den damit geschrieben Ausdruck einen Aufrufausdruck.
Vergleich mit dem Zirkumfixoperator »(« »)«
Die hier neu vorgestellte Schreibweise von Aufrufen mit Klammern »(« »)« ist nicht mit dem früher eingeführten Zirkumfixoperator »(« »)« zu verwechseln, dessen Klammern wir auch als „Ausdruckklammern“ bezeichnet hatten.
- Syntax des schon früher behandelten Zirkumfixoperators »(« »)«
Ausdruck
.-. .----------. .-.
--->· ( ·--->| Ausdruck |--->· ) ·-->
'-' '----------' '-'
Die hier neu behandelten Aufrufklammern stehen immer direkt hinter einem Funktionsnamen, wie beispielsweise in »RAND()« und bilden mit ihm zusammen einen Ausdruck, während die früher behandelten Ausdruckklammern um einen Ausdruck herum geschrieben werden und mit diesem einen neuen Ausdruck, wie beispielsweise »(65)«, bilden.
(Wir sagen, daß Klammern leer seien und direkt hinter einen Namen stehen, auch wenn die Klammern noch Leerraum enthalten oder von dem voranstehenden Namen durch Leeraum getrennt sind, da Leerraum hier keine Rolle spielt.)
Funktionsnamen
Die Groß- und Kleinschreibung von Funktionsnamen nicht signifikant (das heißt: die Groß- und Kleinschreibung von Funktionsnamen ist egal.)
Der eben neu eingeführte Aufrufausdruck beginnt mit einem Namen, allerdings sind nur bestimmte Namen erlaubt. Wir zeigen hier zunächst ein Beispiel mit dem Namen »RAND«.
Eingabe
SELECT RAND();
Ausgabe (gekürzt)
0.5630878568955987
(Eine mögliche Aussprache von “random ” ist /ˈˈrænd/.)
Der Name »RAND« steht für ein Programm, welches zur Laufzeit bei der Auswertung des Aufrufsausdrucks »RAND« gestartet wird.
Solch ein Programm, das von einem anderen Programm aus aufgerufen wird, wird auch als Unterprogramm bezeichnet. Insbesondere in SQL nennt man solch ein Unterprogramm manchmal eine Funktion. »RAND« ist eine Funktion.
Als Name im Aufrufausdruck sind nur Namen erlaubt, die auch eine Funktion bezeichnen. Solche Namen bezeichnen wir als Funktionsnamen.
Die Schreibweise eines Ausdrucks mit einem Funktionsnamen und einem folgenden Paar runder Klammern nennen wir einen Funktionsaufrufausdruck oder – kurz – einen Aufrufausdruck.
Funktionsnamen sind im allgemeinen keine Ausdrücke, sie haben also im allgemeinen keinen Wert! Während also beispielsweise der Spaltenname »VORNAME« ein Ausdruck ist, ist »RAND« alleine kein Ausdruck. Man kann »RAND« lediglich als einen Namen oder als eine Angabe bezeichnen.
Das folgende Beispiel zeigt, daß es in MySQL im allgemeinen erlaubt ist, eine Spalte mit dem Namen einer Funktion anzulegen.
- Konsole
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET sql_mode = '';
DROP SCHEMA IF EXISTS S; CREATE SCHEMA S; USE S;
CREATE TABLE A ( RAND VARCHAR( 255 ) );
INSERT INTO A ( RAND ) VALUES ( 'alpha' );
In älteren Versionen von MySQL mußte man darauf achten, daß bei einem Funktionsaufruf die runde Klammern auf »(« immer direkt auf den Funktionsnamen folgt. Umgekehrt sollte auf Namen, die keinen Funktionsnamen sein sollen, nie direkt einee runden Klammer auf »(« folgen; sie sollte beispielsweise mit einem Leerzeichen abgetrennt sein. In neueren Versionen von MySQL ist diese Unterscheidung für viele Funktionen nicht mehr so wichtig, aber es gibt immer noch einige Funktionen, bei denen sie beachtet werden muß.
Das folgenden Beispiel zeigt, daß im Falle des Namens »RAND« das Leerzeichen keine Rolle spielt. Wenn dem Name keine Klammern folgen, so steht er für die Spalte »RAND«, wenn ihm Klammern folgen, so steht er für die Funktion »RAND«. Trotzdem sollten Funktionsaufrufe immer ohne Leerzeichen zwischen Funktionsnamen und der Runden Klammer auf »(« geschrieben werden und alle anderen Fälle mit (wie beispielsweise oben »TABLE A («).
- Konsole
SET sql_mode = '';
SELECT RAND, RAND(), RAND () FROM A;
+-------+--------------------+--------------------+
| RAND | RAND() | RAND () |
+-------+--------------------+--------------------+
| alpha | 0.3467589452366894 | 0.5823355238720174 |
+-------+--------------------+--------------------+
Die Einstellung »IGNORE_SPACE« ändert das Verhalten von MySQL in Zusammenhang mit dem angesprochenen Leerzeichen etwas ab. Aber dies betrifft nur wenige kritische Funktionsnamen. Im Falle der Funktion »RAND« ändert sich durch dieses Einstellung nichts.
- Konsole
SET sql_mode = 'IGNORE_SPACE';
SELECT RAND, RAND(), RAND () FROM A;
+-------+--------------------+---------------------+
| RAND | RAND() | RAND () |
+-------+--------------------+---------------------+
| alpha | 0.5241132690795821 | 0.38381974434835814 |
+-------+--------------------+---------------------+
Ohne »IGNORE_SPACE« wird ein Name mit einer folgenden runden Klammern auf »(« immer als Funktionsname angesehen.
Mit »IGNORE_SPACE« darf in vielen Fällen auch Leerraum zwischen Funktionsnamen und einer folgenden runden Klammer auf »(« eingefügt werden. Dadurch können einige Funktionsnamen aber nicht mehr als Namen für andere Zwecke verwendet werden, da sie dann dort nicht mehr durch ein folgendes Leerzeichen als Name für andere Zweck gekennzeichnet werden können. (Allerdings könnten solche Namen durch Zitieren doch noch für andere Zwecke verwendet werden.) »IGNORE_SPACE« wird auch durch »ANSI« aktiviert.
In einem Funktionsaufruf sollte die runde Klammer auf »(« direkt hinter dem Funktionsnamen stehen.
In allen anderen Fällen sollte zwischen einem Wort und einer runden Klammer auf »(« ein Leerzeichen stehen.
- Weitere Quellen zu diesem Thema *
http://dev.mysql.com/doc/en/function-resolution.html
http://dev.mysql.com/doc/en/sql-mode.html
http://en.wikibooks.org/wiki/MySQL/Language/Functions
Die Auswertung von Aufrufausdrücken
Die Funktion »RAND« legt – wie gesagt – beim Ablauf des obenstehenden Programms den Wert des Aufrufausdrucks »RAND()« fest. Jener Wert wird dann von unserem Aufrufrahmen ausgegeben.
»RAND()« bedeutet: „Der Wert dieses Ausdrucks soll von dem Programm »RAND« festgelegt werden.“
Bei der Auswertung eines Aufrufausdrucks wird also das von dem Funktionsnamen angegebene Programm (die Funktion) gestartet (den nur dann kann jenes Programm den Wert des Aufrufausdrucks festlegen). Den Start und die Ausführung jenes Programms nennt man auch Aufrufvorgang.
Die Auswertung eines Aufrufausdrucks der Eingabe bewirkt den Aufrufvorgang bei der Abarbeitung der Eingabe.
Wenn es dem Zusammenhang entnommen werden kann, ob ein Aufrufausdruck oder ein Aufrufvorgang gemeint ist oder wenn die Unterscheidung nicht wichtig ist, spricht man einfach nur von einem Aufruf.
Startet man dasselbe Programm ein zweites Mal, so kann ein anderer Wert erscheinen:
Eingabe
SELECT RAND();
Ausgabe
0.522884334994247
Eingabe
SELECT RAND();
Ausgabe
0.8528461445615125
Der Wert des Aufrufausdrucks »RAND()« ist ein double-Wert, der bei jeder seiner Auswertungen (bei jeder Programmausführung) zwischen 0 (einschließlich) und ‹ 1−2⁻⁵³ › (also 0,99999999999999988897769753748434595763683319091796875) (einschließlich) liegt; man sagt auch, er liege zwischen 0 (einschließlich) und 1 (ausschließlich). Mehrere Auswertungen ergeben mehr oder weniger zufällige Werte, die gleichmäßig über diesen Bereich verteilt sind, die sogenannten Pseudozufallszahlen.
Sortieren nach Zufallszahlen
Im folgenden Beispiel wird eine zufällige Zeile aus einer Tabelle ausgewählt, indem die Tabelle zunächst nach Zufallszahlen sortiert wird (»ORDER BY RAND()« wertet »RAND()« für jede Zeile neu aus) und dann die oberste Zeile ausgewählt wird.
main.sql
WARNINGS; SET sql_mode = 'ANSI,TRADITIONAL';
DROP SCHEMA IF EXISTS S; CREATE SCHEMA S; USE S;CREATE TABLE KUNDE ( KUNDE INT PRIMARY KEY, VORNAME VARCHAR( 255 ), NACHNAME VARCHAR( 255 ));
INSERT INTO KUNDE( KUNDE, VORNAME, NACHNAME )VALUES( 23, 'Friederike', 'Nordbeck' );
INSERT INTO KUNDE( KUNDE, VORNAME, NACHNAME )VALUES( 2, 'Michael', 'Rosowski' );
INSERT INTO KUNDE( KUNDE, VORNAME, NACHNAME )VALUES( 14, 'Birgit', 'Rosowski' );
INSERT INTO KUNDE( KUNDE, VORNAME, NACHNAME )VALUES( 9, 'Bodo', 'Rosowski' );
INSERT INTO KUNDE( KUNDE, VORNAME, NACHNAME )VALUES( 6, 'Simon', 'Rosowski' );
INSERT INTO KUNDE( KUNDE, VORNAME, NACHNAME )VALUES( 5, 'Frank', 'Aldegeerds' );
INSERT INTO KUNDE( KUNDE, VORNAME, NACHNAME )VALUES( 1, 'Eelco', 'Fischbach' );SELECT VORNAME, NACHNAME FROM KUNDE ORDER BY RAND() LIMIT 1;
- Protokoll
+---------+-----------+
| VORNAME | NACHNAME |
+---------+-----------+
| Eelco | Fischbach |
+---------+-----------+- Protokoll (Erneutes Ausführen derselben SELECT-Abfrage)
+---------+----------+
| VORNAME | NACHNAME |
+---------+----------+
| Simon | Rosowski |
+---------+----------+
Weitere nützliche Funktionen
Anzeige des Namens der mit »USE« eingestellten Datenbank
SELECT DATABASE();
SELECT SCHEMA();
Anzeige der Version des Datenbanksystems
SELECT VERSION();
Die Kreiszahl
SELECT PI();
Der Benutzer, wie er sich ausgab
SELECT USER();
SELECT SESSION_USER();
SELECT SYSTEM_USER();
Der vom Server zugeteilte Benutzer
SELECT CURRENT_USER();
Kennung der aktuellen Datenbankverbindung
SELECT CONNECTION_ID();
Anzahl der durch das letzte Einfügekommando veränderten Zeilen
SELECT ROW_COUNT();
Mehr Erklärungen dazu
http://dev.mysql.com/doc/en/information-functions.html
Übungsfragen
? Lexikalische Einheiten zählen
Wie viele lexikalische Einheiten enthält der Aufrufausdruck »RAND()«?