Martin'in yanıtıyla daha fazla uğraşmak yerine, POWER()
buraya ilişkin diğer bulgularımı ekleyeceğim .
Pantolonlarınıza tutun.
önsöz
İlk olarak, size şu MSDN belgeleri olanPOWER()
A'yı sergiliyorum :
Sözdizimi
POWER ( float_expression , y )
Argümanlar
float_expression
Şamandıra türünün veya dolaylı olarak şamandıra dönüştürülebilen türün bir ifadesidir.
Dönüş Türleri
İle aynı float_expression
.
POWER()
Dönüş türünün son satırının okunmasıyla sonuçlanabilir FLOAT
, ancak tekrar okunur. float_expression
"şamandıra türünden veya dolaylı olarak şamandıra dönüştürülebilen türden" dir. Yani, ismine rağmen, float_expression
aslında a FLOAT
, a DECIMAL
veya bir olabilir INT
. Çıktısı ile POWER()
aynı olduğundan float_expression
, bu türlerden biri de olabilir.
Bu nedenle, girdiye bağlı dönüş türlerine sahip bir skaler fonksiyonumuz var. Olabilir mi?
Gözlemler
Size POWER()
, girdisine bağlı olarak çıkışını farklı veri türlerine aktardığını gösteren bir test olan B'yi sergiliyorum .
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;
İlgili sonuçlar:
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
Görünen şey, buna dahil olmayan, ona uyan en küçük tipe POWER()
dökülmesidir .float_expression
BIGINT
Bu nedenle, SELECT POWER(10.0, 38);
çünkü bir taşma hatası ile başarısız 10.0
döküm yapılmasını alır NUMERIC(38, 1)
10 Sonuç alacak yeterince büyük olmadığı 38 . Çünkü 10 38 ondalık basamaktan önce 39 basamak alacak şekilde genişler, oysa ondalık NUMERIC(38, 1)
basamaktan önce 37 basamak artı ondan sonra bir basamak depolayabilir. Bu nedenle, NUMERIC(38, 1)
tutabileceği maksimum değer 10 37 - 0.1'dir.
Bu anlayışla donanmış bir taşma arızasını aşağıdaki gibi düzenleyebilirim.
SELECT POWER(1000000000, 3); -- one billion
Bir milyar (ilk örnekteki bir trilyonun aksine, kullanılan NUMERIC(38, 0)
), bir sığacak kadar küçüktür INT
. Bununla birlikte, üçüncü güce yükseltilen bir milyar INT
, bu nedenle taşma hatası için çok büyük .
Diğer bazı işlevler, çıktı türlerinin girdilerine bağlı olduğu benzer davranış gösterir:
- Matematiksel fonksiyonlar :
POWER()
, CEILING()
, FLOOR()
, RADIANS()
, DEGREES()
, veABS()
- Sistem fonksiyonları ve ifadeler :
NULLIF()
, ISNULL()
, COALESCE()
, IIF()
, CHOOSE()
, ve CASE
ifadeleri
- Aritmetik işleçler : Değişkenler adlandırılmış veri türünde olduğunda hem
SELECT 2 * @MAX_INT;
ve hem de SELECT @MAX_SMALLINT + @MAX_SMALLINT;
örneğin aritmetik taşmalara neden olur.
Sonuç
Bu özel durumda, çözüm kullanmaktır SELECT POWER(1e1, precision)...
. Bu yana tüm olası hassasiyetleri için çalışacaktır 1e1
için döküm alır FLOAT
tutabilir, gülünç sayıda .
Bu işlevler çok yaygın olduğundan, sonuçlarınızın yuvarlanabileceğini veya davranışları nedeniyle taşma hatalarına neden olabileceğini anlamak önemlidir. Çıktınız için belirli bir veri türünü bekliyorsanız veya ona güveniyorsanız, ilgili girişi açıkça gerektiği gibi yayınlayın.
Yani çocuklar, şimdi bunu bildiğinize göre, ileri gidip gelişebilirsiniz.