Anstatt mich weiter in Martins Antwort einzumischen, füge ich den Rest meiner Erkenntnisse POWER()
hier hinzu.
Halte deinen Schlüpfer fest.
Präambel
Zunächst stellePOWER()
ich Ihnen A vor, die MSDN-Dokumentation für :
Syntax
POWER ( float_expression , y )
Argumente
float_expression
Ist ein Ausdruck vom Typ float oder von einem Typ, der implizit in float konvertiert werden kann.
Rückgabetypen
Gleich wie float_expression
.
Sie können aus dem Lesen der letzten Zeile schließen, POWER()
die den Rückgabetyp hat FLOAT
, aber noch einmal lesen. float_expression
ist "vom Typ float oder von einem Typ, der implizit in float konvertiert werden kann". Trotz seines Namens float_expression
kann es sich also tatsächlich um eine FLOAT
, eine DECIMAL
oder eine handeln INT
. Da die Ausgabe von POWER()
die gleiche wie die von ist float_expression
, kann es sich auch um einen dieser Typen handeln.
Wir haben also eine Skalarfunktion mit Rückgabetypen, die von der Eingabe abhängen. Könnte es sein?
Beobachtungen
Ich präsentiere Ihnen Exponat B, einen Test, der zeigt, dass POWER()
seine Ausgabe in Abhängigkeit von seiner Eingabe in verschiedene Datentypen umgewandelt wird .
SELECT
POWER(10, 3) AS int
, POWER(1000000000000, 3) AS numeric0 -- one trillion
, POWER(10.0, 3) AS numeric1
, POWER(10.12305, 3) AS numeric5
, POWER(1e1, 3) AS float
INTO power_test;
EXECUTE sp_help power_test;
DROP TABLE power_test;
Die relevanten Ergebnisse sind:
Column_name Type Length Prec Scale
-------------------------------------------------
int int 4 10 0
numeric0 numeric 17 38 0
numeric1 numeric 17 38 1
numeric5 numeric 17 38 5
float float 8 53 NULL
Was passiert zu sein scheint , ist , dass die POWER()
Abgüsse float_expression
in die kleinste Art , dass es passt, ohne BIGINT
.
Daher SELECT POWER(10.0, 38);
schlägt mit einem Überlauf - Fehler , da 10.0
cast wird NUMERIC(38, 1)
das nicht groß genug ist , um das Ergebnis von 10 zu halten , 38 . Dies liegt daran, dass 10 38 erweitert wird, um 39 Stellen vor der Dezimalstelle zu erhalten, wohingegen NUMERIC(38, 1)
37 Stellen vor der Dezimalstelle und eine Stelle danach gespeichert werden können. Daher kann der Maximalwert NUMERIC(38, 1)
10 37 - 0,1 betragen.
Mit diesem Verständnis kann ich einen weiteren Überlauffehler wie folgt beheben.
SELECT POWER(1000000000, 3); -- one billion
Eine Milliarde (im Gegensatz zu einer Billion aus dem ersten Beispiel, auf das gegossen wird NUMERIC(38, 0)
) ist gerade klein genug, um in eine zu passen INT
. Eine auf die dritte Potenz erhöhte Milliarde ist jedoch zu groß INT
, daher der Überlauffehler.
Einige andere Funktionen weisen ein ähnliches Verhalten auf, wobei der Ausgabetyp von der Eingabe abhängt:
- Mathematische Funktionen :
POWER()
, CEILING()
, FLOOR()
, RADIANS()
, DEGREES()
, undABS()
- Systemfunktionen und Ausdrücke :
NULLIF()
, ISNULL()
, COALESCE()
, IIF()
, CHOOSE()
, und CASE
Ausdrücke
- Arithmetische Operatoren : Sowohl
SELECT 2 * @MAX_INT;
als SELECT @MAX_SMALLINT + @MAX_SMALLINT;
auch führen beispielsweise zu arithmetischen Überläufen, wenn die Variablen den genannten Datentyp haben.
Fazit
In diesem speziellen Fall ist die Lösung zu verwenden SELECT POWER(1e1, precision)...
. Dies funktioniert für alle möglichen Präzisionen, da es auf 1e1
geworfen wird FLOAT
, was lächerlich große Zahlen enthalten kann .
Da diese Funktionen so alltäglich sind, ist es wichtig zu verstehen, dass Ihre Ergebnisse aufgrund ihres Verhaltens gerundet sein oder Überlauffehler verursachen können. Wenn Sie einen bestimmten Datentyp für Ihre Ausgabe erwarten oder sich darauf verlassen, setzen Sie die entsprechende Eingabe nach Bedarf explizit um.
Also, Kinder, jetzt, wo Sie das wissen, können Sie ausgehen und gedeihen.