Alih-alih mencampuri jawaban Martin lebih jauh, saya akan menambahkan sisa temuan saya mengenai POWER()
sini.
Pegang celana Anda.
Pembukaan
Pertama, saya sajikan kepada Anda pameran A, dokumentasi MSDN untukPOWER()
:
Sintaksis
POWER ( float_expression , y )
Argumen
float_expression
Adalah ekspresi tipe float atau tipe yang dapat secara implisit dikonversi menjadi float.
Jenis pengembalian
Sama seperti float_expression
.
Anda dapat menyimpulkan dari membaca baris terakhir yang POWER()
merupakan tipe pengembaliannya FLOAT
, tetapi baca lagi. float_expression
adalah "tipe float atau tipe yang secara implisit dapat dikonversi menjadi float". Jadi, terlepas dari namanya, float_expression
mungkin sebenarnya a FLOAT
, a DECIMAL
, atau a INT
. Karena output dari POWER()
adalah sama dengan float_expression
, juga mungkin juga salah satu dari jenis mereka.
Jadi kami memiliki fungsi skalar dengan tipe pengembalian yang bergantung pada input. Mungkinkah?
Pengamatan
Saya mempersembahkan kepada Anda pameran B, sebuah tes yang menunjukkan bahwa POWER()
keluarannya untuk tipe data yang berbeda tergantung pada inputnya .
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;
Hasil yang relevan adalah:
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
Apa yang tampaknya terjadi adalah yang POWER()
dilemparkan float_expression
ke dalam tipe terkecil yang cocok, tidak termasuk BIGINT
.
Oleh karena itu, SELECT POWER(10.0, 38);
gagal dengan kesalahan limpahan karena 10.0
dilemparkan ke NUMERIC(38, 1)
yang tidak cukup besar untuk menampung hasil 10 38 . Itu karena 10 38 mengembang untuk mengambil 39 digit sebelum desimal, sedangkan NUMERIC(38, 1)
dapat menyimpan 37 digit sebelum desimal plus satu setelahnya. Oleh karena itu, nilai maksimum yang NUMERIC(38, 1)
dapat disimpan adalah 10 37 - 0,1.
Berbekal pemahaman ini saya dapat menyusun kegagalan melimpah lainnya sebagai berikut.
SELECT POWER(1000000000, 3); -- one billion
Satu miliar (berlawanan dengan satu triliun dari contoh pertama, yang dilemparkan ke NUMERIC(38, 0)
) hanya cukup kecil untuk ditampung dalam INT
. Namun, satu miliar dinaikkan menjadi kekuatan ketiga, terlalu besar untuk ituINT
, karenanya kesalahan melimpah.
Beberapa fungsi lain menunjukkan perilaku yang serupa, di mana tipe keluarannya bergantung pada inputnya:
- Fungsi matematika :
POWER()
, CEILING()
, FLOOR()
, RADIANS()
, DEGREES()
, danABS()
- Fungsi sistem dan ekspresi :
NULLIF()
, ISNULL()
, COALESCE()
, IIF()
, CHOOSE()
, dan CASE
ekspresi
- Operator aritmatika : Baik
SELECT 2 * @MAX_INT;
dan SELECT @MAX_SMALLINT + @MAX_SMALLINT;
, misalnya, menghasilkan aritmatika meluap ketika variabel dari tipe data yang disebut.
Kesimpulan
Dalam kasus khusus ini, solusinya adalah menggunakan SELECT POWER(1e1, precision)...
. Ini akan bekerja untuk semua kemungkinan precisioning sejak 1e1
dilemparkan ke FLOAT
, yang dapat menyimpan jumlah yang sangat besar .
Karena fungsi-fungsi ini sangat biasa, penting untuk dipahami bahwa hasil Anda mungkin bulat atau dapat menyebabkan kesalahan melimpah karena perilaku mereka. Jika Anda mengharapkan atau mengandalkan tipe data spesifik untuk output Anda, berikan input yang relevan secara eksplisit jika diperlukan.
Jadi anak-anak, sekarang Anda tahu ini, Anda mungkin maju dan makmur.