plsql小寫金額轉大寫金額函式

xypincle發表於2017-02-19

  1. create or replace function comm.F_upper_money(p_num in number default null)
  2.   return nvarchar2 is
  3.   /*Ver:1.0 Created By xsb on 2003-8-18 For:
  4.   將金額數字(單位元)轉換為大寫(採用從低至高演算法)
  5.   數字整數部分不得超過16位,可以是負數。
  6.   Ver:1.1 Modified By xsb on 2003-8-20 For:個位數處理也放在For迴圈中。
  7.   Ver:1.2 Modified By xsb on 2003-8-22 For:分後不帶整字。
  8.   Ver:1.3 Modified By xsb on 2003-8-28 For:完善測試用例。
  9.   測試用例:
  10.   SET HEAD OFF
  11.   SET FEED OFF
  12.   select '無引數時='||f_upper_money() from dual;
  13.   select 'null='||f_upper_money(null) from dual;
  14.   select '0='||f_upper_money(0) from dual;
  15.   select '0.01='||f_upper_money(0.01) from dual;
  16.   select '0.126='||f_upper_money(0.126) from dual;
  17.   select '01.234='||f_upper_money(01.234) from dual;
  18.   select '10='||f_upper_money(10) from dual;
  19.   select '100.1='||f_upper_money(100.1) from dual;
  20.   select '100.01='||f_upper_money(100.01) from dual;
  21.   select '10000='||f_upper_money(10000) from dual;
  22.   select '10012.12='||f_upper_money(10012.12) from dual;
  23.   select '20000020.01='||f_upper_money(20000020.01) from dual;
  24.   select '3040506708.901='||f_upper_money(3040506708.901) from dual;
  25.   select '40005006078.001='||f_upper_money(40005006078.001) from dual;
  26.   select '-123456789.98='||f_upper_money(-123456789.98) from dual;
  27.   select '123456789123456789.89='||f_upper_money(123456789123456789.89) from dual;

  28.   */
  29.   Result nvarchar2(100); --返回字串
  30.   num_round nvarchar2(100) := to_char(abs(round(p_num, 2))); --轉換數字為小數點後2位的字元(正數)
  31.   num_left nvarchar2(100); --小數點左邊的數字
  32.   num_right nvarchar2(2); --小數點右邊的數字
  33.   str1 nchar(10) := '零壹貳叄肆伍陸柒捌玖'; --數字大寫
  34.   str2 nchar(16) := '元拾佰仟萬拾佰仟億拾佰仟萬拾佰仟'; --數字位數(從低至高)
  35.   num_pre number(1) := 1; --前一位上的數字
  36.   num_current number(1); --當前位上的數字
  37.   num_count number := 0; --當前數字位數

  38. begin
  39.   if p_num is null then
  40.     return null;
  41.   end if; --轉換數字為null時返回null

  42.   select to_char(nvl(substr(to_char(num_round),
  43.                             1,
  44.                             decode(instr(to_char(num_round), '.'),
  45.                                    0,
  46.                                    length(num_round),
  47.                                    instr(to_char(num_round), '.') - 1)),
  48.                      0))
  49.     into num_left
  50.     from dual; --取得小數點左邊的數字
  51.   select substr(to_char(num_round),
  52.                 decode(instr(to_char(num_round), '.'),
  53.                        0,
  54.                        length(num_round) + 1,
  55.                        instr(to_char(num_round), '.') + 1),
  56.                 2)
  57.     into num_right
  58.     from dual; --取得小數點右邊的數字

  59.   if length(num_left) > 16 then
  60.     return '**********';
  61.   end if; --數字整數部分超過16位時

  62.   --採用從低至高的演算法,先處理小數點右邊的數字
  63.   if length(num_right) = 2 then
  64.     if to_number(substr(num_right, 1, 1)) = 0 then
  65.       result := '零' ||
  66.                 substr(str1, to_number(substr(num_right, 2, 1)) + 1, 1) || '分';
  67.     else
  68.       result := substr(str1, to_number(substr(num_right, 1, 1)) + 1, 1) || '角' ||
  69.                 substr(str1, to_number(substr(num_right, 2, 1)) + 1, 1) || '分';
  70.     end if;
  71.   elsif length(num_right) = 1 then
  72.     result := substr(str1, to_number(substr(num_right, 1, 1)) + 1, 1) || '角整';
  73.   else
  74.     result := '整';
  75.   end if;
  76.   --再處理小數點左邊的數字
  77.   for i in reverse 1 .. length(num_left) loop
  78.     --(從低至高)
  79.     num_count := num_count + 1; --當前數字位數
  80.     num_current := to_number(substr(num_left, i, 1)); --當前位上的數字
  81.     if num_current > 0 then
  82.       --當前位上數字不為0按正常處理
  83.       result := substr(str1, num_current + 1, 1) ||
  84.                 substr(str2, num_count, 1) || result;
  85.     else
  86.       --當前位上數字為0時
  87.       if mod(num_count - 1, 4) = 0 then
  88.         --當前位是元、萬或億時
  89.         result := substr(str2, num_count, 1) || result;
  90.         num_pre := 0; --元、萬,億前不準加零
  91.       end if;
  92.       if num_pre > 0 or length(num_left) = 1 then
  93.         --上一位數字不為0或只有個位時
  94.         result := substr(str1, num_current + 1, 1) || result;
  95.       end if;
  96.     end if;
  97.     num_pre := num_current;
  98.   end loop;

  99.   if p_num < 0 then
  100.     --轉換數字是負數時
  101.     result := '負' || result;
  102.   end if;

  103.   return Result;

  104. exception
  105.   when others then
  106.     raise_application_error(-20001, '數字轉換大寫出現錯誤!' || sqlerrm);
  107. end;

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28878983/viewspace-2133889/,如需轉載,請註明出處,否則將追究法律責任。

相關文章