.关于货币大写的探索
尝试了一下货币的大写的方法,自己从论坛上看到,到自己亲手实践,已经可以实现上述的需求,中间思路和算法也更换了几次写出来程序的雏形,有待优化的地方,但是作为自己的思路,把自己的算法记录下来,待以后进一步改进。
max_num number := 0;
v_num number := 0;
v_char varchar2(200);
retcode number:=0;
errbuf varchar2(200);
Result varchar2(200);
v_error exception;
begin
if length(money)>9 then
raise v_error;
end if;
max_num:=length(money);
v_num := max_num;
loop
v_char:=substr(money, v_num, 1);
case
when v_num = max_num and substr(money, v_num, 1)<>0 then
result := v_char || '元整' || result;
when v_num = max_num and substr(money, v_num, 1)=0 then
result := '元整' || result;
when (v_num = max_num-1 or v_num = max_num-5) and substr(money, v_num, 1)<>0 then
result := v_char || '拾' || result;
when (v_num = max_num-1 or v_num = max_num-5) and substr(money, v_num, 1)=0 then
result := v_char|| result;
when (v_num = max_num-2 or v_num = max_num-6) and substr(money, v_num, 1)<>0 then
result := v_char || '佰' || result;
when (v_num = max_num-2 or v_num = max_num-6) and substr(money, v_num, 1)=0 then
result := v_char|| result;
when (v_num = max_num-3 or v_num = max_num-7) and substr(money, v_num, 1)<>0 then
result := v_char || '仟' || result;
when v_num = max_num-3 and substr(money, v_num, 1)=0 then
result := v_char || result;
when v_num = max_num-4 and substr(money, v_num, 1)<>0 then
result := v_char || '万' || result;
when v_num = max_num-4 and substr(money, v_num, 1)=0 then
result := '万'|| result;
when v_num = max_num-8 and substr(money, v_num, 1)<>0 then
result := v_char || '亿' || result;
when v_num = max_num-8 and substr(money, v_num, 1)=0 then
result := '亿'|| result;
else retcode:=2;
end case;
v_num := v_num - 1;
exit when v_num=0;
end loop;
select translate(regexp_replace(regexp_replace(result,'0+(元|万)','\1'),'0+','0'),'0123456789','零壹贰叁肆伍陆柒捌玖')
into Result
from dual;
return(Result);
exception
when v_error then
raise_application_error(1,'超出了计算范围');
when others then
retcode := 2 ;
errbuf := sqlcode||': '||sqlerrm ;
raise_application_error(2,errbuf);
end lcw_get_money;
return varchar2 is
c_money VARCHAR2(12);
b_string VARCHAR2(80);
m_string VARCHAR2(60) := '分角圆拾佰仟万拾佰仟亿';
n_string VARCHAR2(40) := '壹贰叁肆伍陆柒捌玖';
n CHAR;
len NUMBER(10);
i NUMBER(10);
tmp NUMBER(12);
is_zj BOOLEAN;
z_count NUMBER(10);
l_money NUMBER;
l_money1 NUMBER;
l_sign VARCHAR2(10);
l_money1 :=to_number(money);
l_money :=abs(money);
IF l_money1 < 0 THEN
l_sign := '负' ;
ELSE
l_sign := '';
END IF;
tmp := round(l_money, 2) * 100;
c_money := rtrim(ltrim(to_char(tmp, '999999999999')));
len := length(c_money);
is_zj := TRUE;
z_count := 0;
i := 0;
WHILE i < len LOOP
i := i + 1;
n := substr(c_money, i, 1);
IF n = '0' THEN
IF len - i = 6 OR len - i = 2 OR len = i THEN
IF is_zj THEN
b_string := substr(b_string, 1, length(b_string) - 1);
is_zj := FALSE;
END IF;
IF len - i = 6 THEN
b_string := b_string || '万';
END IF;
IF len - i = 2 THEN
b_string := b_string || '圆';
END IF;
IF len = i THEN
b_string := b_string || '整';
END IF;
z_count := 0;
ELSE
IF z_count = 0 THEN
b_string := b_string || '零';
is_zj := TRUE;
END IF;
z_count := z_count + 1;
END IF;
ELSE
b_string := b_string || substr(n_string, to_number(n), 1) ||
substr(m_string, len - i + 1, 1);
z_count := 0;
is_zj := FALSE;
END IF;
END LOOP;
b_string := l_sign || b_string ;
RETURN b_string;
EXCEPTION
WHEN OTHERS THEN
RETURN(SQLERRM);
END;
经过中午的推敲,咱明白了同事的做法的技巧思路在于考虑加0策略,而我自己思路在于减0,由于需要加0的情况较少,所以此题更适合采用加0算法。于是咱就用新学的raise_application_error 的函数进行了,从右向左的扫描,成功的完成如上的需求:
3、改良过的程序
create or replace function lcw_convert_money(money in number) return varchar2 is
money_1 number;
max_num number := 0;
m_char varchar2(18):='壹贰叁肆伍陆柒捌玖';
n_char varchar2(22):='分角圆拾佰仟万拾佰仟亿';
v_num number := 0;
v_char varchar2(200);
v_judge number;
Result varchar2(200);
begin
money_1:=money*100;
max_num:=length(money_1);
v_num := max_num;
case when max_num>11 then
raise_application_error(-20988,'超出了函数的运算范围!');
else
for i in 1..v_num loop
v_char:=substr(money_1, v_num,1);
case when v_char=0 then
case when v_num=max_num or max_num-v_num=2 or max_num-v_num=6 then
case when v_num=max_num then
result:= '整';
when max_num-v_num=2 then
result:='圆'||result;
when max_num-v_num=6 then
result:='万'||result;
end case;
else case when v_judge=0 then
result:='零'||result;
v_judge:=1;
else null;
end case;
end case;
else result:=substr(m_char,v_char,1)||substr(n_char,i,1)||result;
v_judge:=0;
end case;
v_num := v_num - 1;
exit when v_num=0;
end loop;
return(Result);
end case;
exception
when others then
return(sqlcode||':'||sqlerrm);
end lcw_convert_money;
经过测试可以顺利完成如上需求,并且中间经过确认case else逻辑判断是并行的,比if..else执行效率要高,也是对咱细节的优化吧。