سؤال

I am using the following temporary table construct inside a user-defined function to calculate fibonacci numbers. Unfortunately, the temp-table construct gives me an arithmetic overflow error for high values, but I don't how to change the data types the temp table is using ...

WITH FIB_SQL(I, RES_1, RES) AS (
    SELECT 1, 0, 1 FROM SYSIBM.SYSDUMMY1
    UNION ALL
    SELECT I+1, RES, RES+RES_1 FROM FIB_SQL WHERE I < 50
)
SELECT MAX(RES) FROM FIB_SQL;

It works for "WHERE I < 40" but not for "WHERE I < 50"

هل كانت مفيدة؟

المحلول

The values in RES and RES_1 are large enough that when you sum the 2 values it results in a value that is large than the data type will store.

Assume the data types are currently integers, you can cast the data types to be bigint as follows:

WITH FIB_SQL(I, RES_1, RES) AS (
    SELECT 1, cast(0 as bigint), cast(1 as bigint) FROM SYSIBM.SYSDUMMY1
    UNION ALL
    SELECT I+1, RES, cast(RES as bigint) + cast(RES_1 as bigint) FROM FIB_SQL WHERE I < 50
)
SELECT MAX(RES) FROM FIB_SQL;

More info about integer (The range of large integers is -2147483648 to +2147483647) http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=%2Fcom.ibm.db2z9.doc.sqlref%2Fsrc%2Ftpc%2Fdb2z_integer.htm

vs. bigint (The range of big integers is -9223372036854775808 to +9223372036854775807) http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=%2Fcom.ibm.db2z9.doc.sqlref%2Fsrc%2Ftpc%2Fdb2z_biginteger.htm

EDIT: This solution using BIGINT will allow you to go up to I < 92, but I < 93 will still give the arithmetic overflow error, b/c then you are outside of the range of allowed BIGINT values.

If you need to use values outside the range of BIGINT, then checkout the decimal and decfloat data types. http://www-01.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/com.ibm.db2z10.doc.intro/src/tpc/db2z_numericdatatypes.dita

Example using the decimal data type, this allows you to go up to I < 150, which returns 9969216677189303386214405760200:

WITH FIB_SQL(I, RES_1, RES) AS (
    SELECT 1, CAST(0.0 AS decimal(31, 0)), CAST(1 AS decimal(31, 0))
    UNION ALL
    SELECT I+1, RES, CAST(RES +  RES_1 AS decimal(31, 0)) FROM FIB_SQL WHERE I < 150
)
SELECT MAX(RES) FROM FIB_SQL 
--OPTION (MAXRECURSION 150) --in SQL Server this is needed to increase the max recursion setting, not sure if this is needed in DB2 or not.
;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top