Aufrufwandlung in SQL (Aufrufwandlung in SQL), Lektion, Seite 723286
https://www.purl.org/stefan_ram/pub/aufrufwandlung_sql (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
SQL-Kurs

Aufrufwandlung in SQL  (MySQL )

Die Dokumentation der Funktion »RAND« besagt, daß diese mit einem INT-Argument aufgerufen werden kann.

Dokumentation (gekürzt und übersetzt)
RAND( N ) Falls ein INT-Argument angegeben wurde, wird es als interner Startwert verwendet.

Es zeigt sich aber, daß auch DOUBLE-Werte ohne Warnung oder Fehlermeldung akzeptiert werden.

Die folgende Tabelle zeigt die Ergebnisse für verschiedene Argumentausdrücke.

Tabelle
RAND( 3     )  0.9057697559760601
RAND( 3 ) 0.9057697559760601
RAND( 3.1e0 ) 0.9057697559760601
RAND( 3.2e0 ) 0.9057697559760601
RAND( 3.8e0 ) 0.15595286540310166

Man sieht, daß die DOUBLE-Werte bis »3.2e0« zum selben  Ergebnis wie der INT-Wert »3« führen, während der DOUBLE-Wert »3.8e0« zu einem anderen  Ergebnis führt.

Dies legt die Vermutung nahe, daß ein übergebener DOUBLE-Wert zunächst zu einem INT-Wert gerundet  wird, der dann von der Funktion verarbeitet wird. Wir können also annehmen, daß »3.2e0« als »3« interpretiert wird und »3.8e0« als »4«.

Dies ist ein Beispiel für eine Aufrufwandlung : Beim Aufruf einer Funktion wird eine Argumentwert oft stillschweigend in den Typ des Parameters (hier: »INT«) gewandelt.

Empfehlungen zur Aufrufwandlung

Es ist oft davon abzuraten, einen Argumentausdruck, dessen Typ sich vom Typ des Parameters zu unterscheidet zu verwenden, auch wenn es dabei oft keine Warnungen oder Fehlermeldungen gibt.

Im Falle der Funktion »RAND« können wir zunächst ablesen, daß die Dokumentation die Verwendung als internen Startwert nur für INT-Argumente zusagt. Es ist also durch die Dokumentation gar nicht festgelegt, was ein DOUBLE-Argument an dieser Stelle bedeuten soll.

Die Angabe von Nachkommastellen, die ohnehin nicht berücksichtigt werden hat auch keine Vorteile und kann ein Zeichen für Verständnisprobleme des Autors eines Aufrufs sein oder zu Irritationen bei Lesern eines Aufrufs führen.

Die Art der Aufrufwandlung kann auch anders als erwartet sein, was dann zu Fehlern führen könnte. Beispielsweise könnte jemand erwarten, daß Nachkommastellen wie bei der DIV-Division abgeschnitten werden, während sie tatsächlich gerundet werden.

Schließlich kann es sein, daß die nicht dokumentierten Verfahren der Aufrufwandlung in späteren Versionen von MySQL  einmal verändert werden (etwa die Details der Rundung in Grenzfällen) oder vom verwendeten Betriebssystem abhängen.

Die Wandlung des Typs von Werten kostet außerdem Zeit, die Abfragen bremsen kann.

Aus all diesen Gründen sollte ein Programmierer versuchen, für eine aufzurufende Funktion den Typ des Parameters zu ermitteln und dann einen Argumentausdruck mit demselben Typ zu verwenden.

Die stillschweigen Aufrufwandlung ohne Warnungen oder Fehlermeldungen kann dazuführen, daß ein unpassender Typ unbemerkt bleibt.

Aufrufwandlungen mit anderen Typen

In dieser Lektion sollen nicht alle möglichen Typwandlungen behandelt werden. Oben haben wir beispielhaft die Wandlung eines DOUBLE-Argumentausdrucks bei einem INT-Parameter betrachtet.

Man kann sagen, daß die umgekehrte Aufrufwandlung eines INT-Argumentausdruck bei einem DOUBLE-Parameter weniger problematisch ist, weil dort keine Informationen (Nachkommastellen) verloren gehen.

In der Regel wird es auch nicht problematisch sein, einen DECIMAL-Argumentausdruck bei einem DOUBLE-Parameter zu verwenden, da beides Wert von ähnlicher Art sind (Zahlen mit Nachkommastellen). Jedoch können Informationen verloren gehen (der Typ »DECIMAL« kann „genauer“ als »DOUBLE« sein) und die Umwandlung kann Zeit kosten.

Für Zeichenfolgen-Parameter können VARCHAR-Argumentausdrücke verwendet werden. Falls Zahlen verwendet werden, werden sie in eine Zeichenfolge gewandelt, was manchmal ebenfalls zu Überraschungen führen kann, so ergibt das Numerale »1.9999999999999999e0« die Zeichenfolge »'2'«. Umgekehrt können auch VARCHAR-Argumentausdrücke angegeben werden, wenn Zahlen erwartet werden, wie etwa in »RAND( '3' )«. Dies könnte aber auch nur dazu führen, daß ein unpassender Typ einer Spalte unbemerkt bleibt.

Blick in den Quellcode *

Hier zeigen wir für Leser mit C++ -Kenntnissen noch, wie man das Verhalten von »RAND« bei einem DOUBLE-Argument nachfollziehen kann.

Zunächst zeigt der Quelltext von »RAND«, daß »seed_random« aufgerufen wird, falls ein Argument angegeben ist.

item_func.cc
double Item_func_rand::val_real()
{
DBUG_ASSERT(fixed == 1);
if (arg_count)
{
if (!args[0]->const_item())
seed_random(args[0]);

In »seed_random« wird der Wert des Arguments dann mit »val_int« ermittelt.

item_func.cc
void Item_func_rand::seed_random(Item *arg)
{
/*
TODO: do not do reinit 'rand' for every execute of PS/SP if
args[0] is a constant.
*/
uint32 tmp= (uint32) arg->val_int();

In »seed_random« wird der Wert des Arguments dann mit »val_int« ermittelt.

Welche »val_int«-Methode dann genau aufgerufen wird, hängt anscheinend von der Art des Argumentausdrucks ab, aber man kann in einigen Fällen erkennen, daß dann die Funktion »rint« aufgerufen wird, welche ihr Argument rundet.

item.cc (2013)
longlong Item_param::val_int() 
{
switch (state) {
case REAL_VALUE:
return (longlong) rint(value.real);
item.cc
longlong Item_float::val_int(void)
{
DBUG_ASSERT(fixed == 1);
if (value <= (double) LONGLONG_MIN)
{
return LONGLONG_MIN;
}
else if (value >= (double) (ulonglong) LONGLONG_MAX)
{
return LONGLONG_MAX;
}
return (longlong) rint(value);
}
item.h (2013)
class Item_float :public Item_num
{
...
  longlong val_int()
{
DBUG_ASSERT(fixed == 1);
if (value <= (double) LONGLONG_MIN)
{
return LONGLONG_MIN;
}
else if (value >= (double) (ulonglong) LONGLONG_MAX)
{
return LONGLONG_MAX;
}
return (longlong) rint(value);
}

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723286 stefan_ram:723286 Aufrufwandlung in SQL Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723286, slrprddef723286, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/aufrufwandlung_sql