For SEPA (single euro payment area) we like to perform a check if an IBAN (bank account number is correct).
Part of the IBAN number is a check digit which is euqal to 98 - MOD(X,97).
Some countries have an IBAN resulting in X having more than 40 characters.
It looks like the function MOD wont work when X > 38 characters (actually it does not run in error, it just returns 0 in any case).
Any idea how to solve this?
test:
SELECT MOD(221021290110000123452229211210282900128222900,97)
FROM DUAL
=> 0 ??
Many thanks in advance.
Eelco.
that is because we only support 38 to 39 digits of precision. Your number ends in "0" as far as we are concerned:
ops$tkyte%ORA11GR2> set numformat 9999999999999999999999999999999999999999999999999
ops$tkyte%ORA11GR2> select 221021290110000123452229211210282900128222902 from dual;
221021290110000123452229211210282900128222902
--------------------------------------------------
221021290110000123452229211210282900128000000
you cannot put numbers with more than 38 significant digits into an Oracle number - you'll lose some of that precision.
Using the logic gleaned from this page:
http://www.devx.com/tips/Tip/39012 I came up with this:
ops$tkyte%ORA11GR2> select mod( to_number( mod( to_number( substr( str, 1, 30 ) ), 97 ) || substr( str, 31 ) ), 97 ) m
2 from (
3 select '221021290110000123452229211210282900128222902' str
4 from dual
5 )
6 /
M
--------------------------------------------------
16
basically - take the first 30 digits of your number, mod it, concatenate that back onto the rest of the number - which should be small enough to be an Oracle number with full precision, and mod that...
I tested a few values with:
http://www.calculatorpro.com/calculator/modulo-calculator/ which does very large modulo's for us and it seems to work. Please do a little more research on the math behind this to be comfortable with the approach yourself.