注意:当报如下错误时,是因为存储过程中定义的变量值太小,加大它的范围即可。
Caused by: java.sql.SQLException: ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小
ORA-06512: 在 "AP_JXMG.NUM2RMB", line 6
解决办法:如
sch varchar2(20) := '零壹贰叄肆伍陆柒捌玖';
sjin varchar2(50) := '分角圆拾佰仟万拾佰仟亿拾佰仟万拾佰仟';
srmb varchar2(100) := '';
改为
sch varchar2(50) := '零壹贰叄肆伍陆柒捌玖';
sjin varchar2(100) := '分角圆拾佰仟万拾佰仟亿拾佰仟万拾佰仟';
srmb varchar2(200) := '';
--Oracle存储过程实现人民币大小写转换
--使用方法
select num2rmb(3454645435345123.45) RMB from dual;
--创建存储过程
create or replace function num2rmb(je number) return varchar2 is
result varchar2(100);
i pls_integer;
snum varchar2(20) := ltrim(replace(to_char(abs(je),'9999999999999990.99'),'.'));
len pls_integer := length(snum);
sch varchar2(50) := '零壹贰叄肆伍陆柒捌玖';
sjin varchar2(100) := '分角圆拾佰仟万拾佰仟亿拾佰仟万拾佰仟';
srmb varchar2(200) := '';
num Pls_Integer;
jin varchar(2);
s_num pls_integer := 0; --0起始位置
e_num pls_integer := 0; --0结束位置
begin
for i in 1 .. len loop
num := to_number(substr(snum, i, 1));
if num <> 0 then
--非‘0’时处理
if s_num = 0 then
srmb := srmb || substr(sch, num + 1, 1) ||
substr(sjin, len - i + 1, 1);
--前面字符非0时,正常连接。。。
else
srmb := srmb || --否则
case
when s_num = e_num then --前面只有一个0
case s_num
when 7 then
'万' --只处理进位
when 11 then
'亿'
when 15 then
'万'
end
when e_num < 12 then --否则多个0处理
case
when s_num < 7 then
'' --一万以内。。。
when s_num < 11 then
case
when e_num < 8 and s_num < 10 then
'万'
end
when s_num < 15 then
case
when e_num < 12 then
'亿'
end
else
'万亿'
end
when e_num < 16 and s_num > 14 then
'万'
end || case
when s_num > 3 and e_num < 3 then
'圆零'
when e_num = 3 then
'圆'
when e_num not in (7, 11, 15) or s_num - e_num > 2 then
'零'
end;
srmb := srmb || substr(sch, num + 1, 1) ||
substr(sjin, len - i + 1, 1);
end if;
s_num := 0;
e_num := 0;
else
if s_num = 0 then
--当s_num=0时0串起始
s_num := len - i + 1; --记录开始
e_num := s_num;
else
e_num := len - i + 1;
end if;
end if;
end loop;
if s_num <> 0 then
--此时以0结尾
srmb := srmb || case
when s_num = len then
'零圆整' --全0串,加。。。
when s_num = 1 or s_num = 2 then
'整' --分(1),角(2)后加。。。
when s_num < 7 or s_num = 10 then
'圆整'
when s_num < 11 then
'万圆整'
when s_num < 15 then
'亿圆整'
else
'万亿圆整'
end;
else
srmb := srmb || '整'; --不以0结尾,加...
end if;
if je < 0 then
srmb := '负' || srmb;
end if;
return srmb;
end num2rmb;
Java人民币小写转大写
package com.qyj.utils;
import org.apache.commons.lang.StringUtils;
public class MoneyUtil {
//整数部分的人民币大写
private static final String[] NUMBERS = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
//数位部分
private static final String[] IUNIT = {"元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万", "拾", "佰", "仟"};
//小数部分的人民币大写
private static final String[] DUNIT = {"角", "分", "厘"};
//转成中文的大写金额
public static String toChinese(String str) {
//判断输入的金额字符串是否符合要求
if (StringUtils.isBlank(str) || !str.matches("(-)?[\\d]*(.)?[\\d]*")) {
System.out.println("抱歉,请输入数字!");
return str;
}
//判断输入的金额字符串
if ("0".equals(str) || "0.00".equals(str) || "0.0".equals(str)) {
return "零元";
}
//判断是否存在负号"-"
boolean flag = false;
if (str.startsWith("-")) {
flag = true;
str = str.replaceAll("-", "");
}
//如果输入字符串中包含逗号,替换为 "."
str = str.replaceAll(",", ".");
String integerStr;//整数部分数字
String decimalStr;//小数部分数字
//分离整数部分和小数部分
if (str.indexOf(".") > 0) {//整数部分和小数部分
integerStr = str.substring(0, str.indexOf("."));
decimalStr = str.substring(str.indexOf(".") + 1);
} else if (str.indexOf(".") == 0) {//只存在小数部分 .34
integerStr = "";
decimalStr = str.substring(1);
} else { //只存在整数部分 34
integerStr = str;
decimalStr = "";
}
//整数部分超出计算能力,直接返回
if (integerStr.length() > IUNIT.length) {
System.out.println(str + ":超出计算能力");
return str;
}
//整数部分存入数组 目的是为了可以动态的在字符串数组中取对应的值
int[] integers = toIntArray(integerStr);
//判断整数部分是否存在输入012的情况
if (integers.length > 1 && integers[0] == 0) {
System.out.println("抱歉,请输入数字!");
if (flag) {
str = "-" + str;
}
return str;
}
boolean isWan = isWanUnits(integerStr);//设置万单位
//小数部分数字存入数组
int[] decimals = toIntArray(decimalStr);
String result = getChineseInteger(integers, isWan) + getChineseDecimal(decimals);//返回最终的大写金额
if (flag) {
return "负" + result;//如果是负数,加上"负"
} else {
return result;
}
}
//将字符串转为int数组
private static int[] toIntArray(String number) {
//初始化一维数组长度
int[] array = new int[number.length()];
//循环遍历赋值
for (int i = 0; i < number.length(); i++) {
array[i] = Integer.parseInt(number.substring(i, i + 1));
}
return array;
}
//将整数部分转为大写的金额
public static String getChineseInteger(int[] integers, boolean isWan) {
StringBuffer chineseInteger = new StringBuffer("");
int length = integers.length;
// 对于输入的字符串为 "0." 存入数组后为 0
if (length == 1 && integers[0] == 0) {
return "";
}
for (int i = 0; i < length; i++) {
String key = "";//0325464646464
if (integers[i] == 0) {
if ((length - i) == 13)//万(亿)
key = IUNIT[4];
else if ((length - i) == 9) {//亿
key = IUNIT[8];
} else if ((length - i) == 5 && isWan) {//万
key = IUNIT[4];
} else if ((length - i) == 1) {//元
key = IUNIT[0];
}
if ((length - i) > 1 && integers[i + 1] != 0) {
key += NUMBERS[0];
}
}
chineseInteger.append(integers[i] == 0 ? key : (NUMBERS[integers[i]] + IUNIT[length - i - 1]));
}
return chineseInteger.toString();
}
//将小数部分转为大写的金额
private static String getChineseDecimal(int[] decimals) { //角 分 厘 038 壹分捌厘
StringBuffer chineseDecimal = new StringBuffer("");
for (int i = 0; i < decimals.length; i++) {
if (i == 3) {
break;
}
chineseDecimal.append(decimals[i] == 0 ? "" : (NUMBERS[decimals[i]] + DUNIT[i]));
}
return chineseDecimal.toString();
}
//判断当前整数部分是否已经是达到【万】
private static boolean isWanUnits(String integerStr) {
int length = integerStr.length();
if (length > 4) {
String subInteger = "";
if (length > 8) {
subInteger = integerStr.substring(length - 8, length - 4);
} else {
subInteger = integerStr.substring(0, length - 4);
}
return Integer.parseInt(subInteger) > 0;
} else {
return false;
}
}
public static void main(String[] args) {
String number = "1409.59";
String afterStr = MoneyUtil.toChinese(number);
System.out.println(number + ": " + afterStr);//壹仟肆佰零玖元伍角
}
}