1 CREATE OR REPLACE FUNCTION MONEY_TO_CHINESE(MONEY IN VARCHAR2)
2 RETURN VARCHAR2 IS
3 C_MONEY VARCHAR2(12);
4 M_STRING VARCHAR2(60) := '分角圆拾佰仟万拾佰仟亿';
5 N_STRING VARCHAR2(40) := '壹贰叁肆伍陆柒捌玖';
6 B_STRING VARCHAR2(80);
7 N CHAR;
8 LEN NUMBER(3);
9 I NUMBER(3);
10 TMP NUMBER(12);
11 IS_ZERO BOOLEAN;
12 Z_COUNT NUMBER(3);
13 L_MONEY NUMBER;
14 L_SIGN VARCHAR2(10);
15 BEGIN
16 L_MONEY := ABS(MONEY);
17
18 IF MONEY < 0 THEN
19 L_SIGN := '负';
20 ELSE
21 L_SIGN := '';
22 END IF;
23
24 TMP := ROUND(L_MONEY, 2) * 100;
25 C_MONEY := RTRIM(LTRIM(TO_CHAR(TMP, '999999999999')));
26 LEN := LENGTH(C_MONEY);
27 IS_ZERO := TRUE;
28 Z_COUNT := 0;
29 I := 0;
30
31 WHILE I < LEN LOOP
32 I := I + 1;
33 N := SUBSTR(C_MONEY, I, 1);
34
35 IF N = '0' THEN
36 IF LEN - I = 6 OR LEN - I = 2 OR LEN = I THEN
37 IF IS_ZERO THEN
38 B_STRING := SUBSTR(B_STRING, 1, LENGTH(B_STRING) - 1);
39 IS_ZERO := FALSE;
40 END IF;
41
42 IF LEN - I = 6 THEN
43 B_STRING := B_STRING || '万';
44 END IF;
45
46 IF LEN - I = 2 THEN
47 B_STRING := B_STRING || '圆';
48 END IF;
49
50 IF LEN = I THEN
51 B_STRING := B_STRING || '整';
52 END IF;
53
54 Z_COUNT := 0;
55 ELSE
56 IF Z_COUNT = 0 THEN
57 B_STRING := B_STRING || '零';
58 IS_ZERO := TRUE;
59 END IF;
60
61 Z_COUNT := Z_COUNT + 1;
62 END IF;
63 ELSE
64 B_STRING := B_STRING || SUBSTR(N_STRING, TO_NUMBER(N), 1) ||
65 SUBSTR(M_STRING, LEN - I + 1, 1);
66 Z_COUNT := 0;
67 IS_ZERO := FALSE;
68 END IF;
69 END LOOP;
70
71 B_STRING := L_SIGN || B_STRING;
72 RETURN B_STRING;
73 EXCEPTION
74 WHEN OTHERS THEN
75 RETURN(SQLERRM);
76 END;
77
78
79 CREATE OR REPLACE FUNCTION TO_UPPER_NUM
80 (
81 P_NUM IN NUMBER DEFAULT NULL,
82 P_ROUND NUMBER DEFAULT 2, --输出要保留的小数位数
83 P_MONTH NUMBER DEFAULT 1 --输出不为月份或者日时
84 )
85 RETURN VARCHAR2
86 IS
87 /**
88 *阿拉伯数字转化为大写汉字的函数
89 *输入参数转换前的数字,要保留的小数位数(4舍5入可以不输入,默认为小数点后2位)
90 *输出参数为转化后的大写数字
91 *支持小数点和负数,但数字整数部分不能超过16位
92 *支持转换月份和日期,如 SELECT TO_UPPER_NUM('31','3','2') FROM DUAL
93 *--日期例子(年份的转换见另一个函数)
94 * SELECT TO_UPPER_YEAR(TO_CHAR(SYSDATE,'YYYY')) || '年' ||
95 * TO_UPPER_NUM(TO_CHAR(SYSDATE,'MM'),'2','2') || '月' ||
96 * TO_UPPER_NUM(TO_CHAR(SYSDATE,'DD'),'2','2') || '日'
97 * FROM DUAL ;
98 *--货币例子(截取小数点后两位,四舍五入)
99 * SELECT TO_UPPER_NUM(1234.564) FROM dual ;
100 */
101 RESULT NVARCHAR2(100) := ''; --返回大写汉字字符串
102 NUM_ROUND NVARCHAR2(100) := TO_CHAR(ABS(ROUND(P_NUM, P_ROUND))); --转换数字为小数点后p_round位的字符(正数)
103 NUM_LEFT NVARCHAR2(100); --小数点左边的数字
104 NUM_RIGHT NVARCHAR2(100); --小数点右边的数字
105 STR1 NCHAR(10) := '零壹贰叁肆伍陆柒捌玖'; --数字大写
106 STR2 NCHAR(16) := '点拾佰仟万拾佰仟亿拾佰仟万拾佰仟'; --数字位数(从低至高)
107 STR3 NCHAR(10) := '〇一二三四五六七八九'; --月份数字大写
108 STR4 NCHAR(16) := '点十佰仟万拾佰仟亿拾佰仟万拾佰仟'; --数字位数(从低至高)
109 NUM_PRE NUMBER(1) := 1; --前一位上的数字
110 NUM_CURRENT NUMBER(1); --当前位上的数字
111 NUM_COUNT NUMBER := 0; --当前数字位数
112 BEGIN
113 --转换数字为NULL时,返回NULL
114 IF P_NUM IS NULL THEN
115 RETURN NULL;
116 END IF;
117 --如果要转换月份或者日时,则替换临时变量
118 IF P_MONTH <> 1 THEN
119 STR1 := STR3;
120 STR2 := STR4;
121 END IF;
122 --取得小数点左边的数字
123 SELECT TO_CHAR(NVL(SUBSTR(TO_CHAR(NUM_ROUND),
124 1,
125 DECODE(INSTR(TO_CHAR(NUM_ROUND), '.'),
126 0,
127 LENGTH(NUM_ROUND),
128 INSTR(TO_CHAR(NUM_ROUND), '.') - 1)),
129 0))
130 INTO NUM_LEFT
131 FROM DUAL;
132 --取得小数点右边的数字
133 SELECT SUBSTR(TO_CHAR(NUM_ROUND),
134 DECODE(INSTR(TO_CHAR(NUM_ROUND), '.'),
135 0,
136 LENGTH(NUM_ROUND) + 1,
137 INSTR(TO_CHAR(NUM_ROUND), '.') + 1),
138 P_ROUND)
139 INTO NUM_RIGHT
140 FROM DUAL;
141 --数字整数部分超过16位时.采用从低至高的算法,先处理小数点左边的数字
142 IF LENGTH(NUM_LEFT) > 16 THEN
143 RETURN '**********';
144 END IF;
145 FOR I IN REVERSE 1 .. LENGTH(NUM_LEFT) LOOP
146 --(从低至高)
147 NUM_CURRENT := TO_NUMBER(SUBSTR(NUM_LEFT, I, 1)); --当前位上的数字
148 NUM_COUNT := NUM_COUNT + 1; --当前数字位数
149 --当前位上数字不为0按正常处理
150 IF NUM_CURRENT > 0 THEN
151 --如果转换数字最高位是十位,转换后不需要前面的壹,如月份12转换后为拾贰,则
152 IF NUM_CURRENT = 1 AND P_MONTH <> 1 AND NUM_COUNT = 2 THEN
153 RESULT := SUBSTR(STR2, NUM_COUNT, 1) || RESULT;
154 STR1 := STR3;
155 ELSE
156 RESULT := SUBSTR(STR1, NUM_CURRENT + 1, 1)
157 ||SUBSTR(STR2, NUM_COUNT, 1)
158 || RESULT;
159 END IF;
160 ELSE
161 --当前位上数字为0时
162 IF MOD(NUM_COUNT - 1, 4) = 0 THEN
163 --当前位是点、万或亿时
164 RESULT := SUBSTR(STR2, NUM_COUNT, 1) || RESULT;
165 NUM_PRE := 0; --点、万,亿前不准加零
166 END IF;
167 IF NUM_PRE > 0 OR LENGTH(NUM_LEFT) = 1 THEN
168 --上一位数字不为0或只有个位时
169 RESULT := SUBSTR(STR1, NUM_CURRENT + 1, 1) || RESULT;
170 END IF;
171 END IF;
172 NUM_PRE := NUM_CURRENT;
173 END LOOP;
174 --再处理小数点右边的数字
175 IF LENGTH(NUM_RIGHT) > 0 THEN
176 FOR I IN 1 .. LENGTH(NUM_RIGHT) LOOP
177 --(从高至低)
178 NUM_CURRENT := TO_NUMBER(SUBSTR(NUM_RIGHT, I, 1)); --当前位上的数字
179 RESULT := RESULT || SUBSTR(STR1, NUM_CURRENT + 1, 1);
180 END LOOP;
181 ELSE
182 RESULT := REPLACE(RESULT, '点', ''); --无小数时去掉点
183 END IF;
184 --转换数字是负数时
185 IF P_NUM < 0 THEN
186 RESULT := '负' || RESULT;
187 END IF;
188 RETURN RESULT;
189 EXCEPTION
190 WHEN OTHERS THEN
191 DBMS_OUTPUT.PUT_LINE(SQLERRM);
192 RETURN '';
193 END;
194
195
196 CREATE OR REPLACE FUNCTION TO_UPPER_YEAR(YEAR_IN IN VARCHAR2)
197 RETURN VARCHAR2
198 /**
199 *年转化为大写汉字的函数 如将2008转换为二〇〇八
200 *月份和日期转换的可以调用 TO_UPPER_NUM 函数
201 *如SELECT TO_UPPER_NUM('21','2','2') FROM DUAL
202 *查询系统大写年月日如下:
203 *SELECT TO_UPPER_YEAR(TO_CHAR(SYSDATE,'YYYY')) || '年' ||
204 * TO_UPPER_NUM(TO_CHAR(SYSDATE,'MM'),'2','2') || '月' ||
205 * TO_UPPER_NUM(TO_CHAR(SYSDATE,'DD'),'2','2') || '日' SJ
206 *FROM DUAL
207 */
208 IS
209 TEMP VARCHAR2(32767);
210 RESULT VARCHAR2(32767);
211 STR VARCHAR2(32767) := '〇一二三四五六七八九';
212 BEGIN
213 IF YEAR_IN IS NULL THEN
214 RETURN NULL;
215 END IF;
216 FOR I IN 1 .. LENGTH(YEAR_IN)
217 LOOP
218 SELECT SUBSTR(STR, SUBSTR(YEAR_IN,I, 1) + 1, 1)
219 INTO TEMP
220 FROM DUAL;
221 RESULT := RESULT || TEMP;
222 END LOOP;
223 RETURN RESULT;
224 EXCEPTION
225 WHEN OTHERS THEN
226 DBMS_OUTPUT.PUT_LINE(SQLERRM);
227 RETURN '';
228 END;