1. 程式人生 > 實用技巧 >oracle實現阿拉伯數字轉化為大寫漢字的函式

oracle實現阿拉伯數字轉化為大寫漢字的函式


oracle實現阿拉伯數字轉化為大寫漢字的函式

2011-10-28 20:34:331115收藏 分類專欄:oraclePL SQL文章標籤:oraclefunction數字轉換大寫

今天工作中遇到了要改貨幣金額轉換為大寫顯示的需求,找到了一些前輩們的程式碼,總結了一下貼出來,以備以後檢視學習使用.

1.專門用於轉化年份的函式TO_UPPER_YEAR.


  1. CREATE OR REPLACE FUNCTION TO_UPPER_YEAR(YEAR_IN IN VARCHAR2)
  2. RETURN VARCHAR2
  3. /**
  4. *年轉化為大寫漢字的函式 如將2008轉換為二〇〇八
  5. *月份和日期轉換的可以呼叫 TO_UPPER_NUM 函式
  6. *如SELECT TO_UPPER_NUM('21','2','2') FROM DUAL
  7. *查詢系統大寫年月日如下:
  8. *SELECT TO_UPPER_YEAR(TO_CHAR(SYSDATE,'YYYY')) || '年' ||
  9. * TO_UPPER_NUM(TO_CHAR(SYSDATE,'MM'),'2','2') || '月' ||
  10. * TO_UPPER_NUM(TO_CHAR(SYSDATE,'DD'),'2','2') || '日' SJ
  11. *FROM DUAL
  12. */
  13. IS
  14. TEMP VARCHAR2(32767);
  15. RESULT VARCHAR2(32767);
  16. STR VARCHAR2(32767) := '〇一二三四五六七八九';
  17. BEGIN
  18. IF YEAR_IN IS NULL THEN
  19. RETURN NULL;
  20. END IF;
  21. FOR I IN 1 .. LENGTH(YEAR_IN)
  22. LOOP
  23. SELECT SUBSTR(STR, SUBSTR
    (YEAR_IN,I, 1) + 1, 1)
  24. INTO TEMP
  25. FROM DUAL;
  26. RESULT := RESULT || TEMP;
  27. END LOOP;
  28. RETURN RESULT;
  29. EXCEPTION
  30. WHEN OTHERS THEN
  31. DBMS_OUTPUT.PUT_LINE(SQLERRM);
  32. RETURN '';
  33. END;

2.用於阿拉伯數字轉化為大寫漢字的函式TO_UPPER_NUM.


  1. CREATE OR REPLACE FUNCTION TO_UPPER_NUM
  2. (
  3. P_NUM IN NUMBER DEFAULT NULL,
  4. P_ROUND NUMBER DEFAULT 2, --輸出要保留的小數位數
  5. P_MONTH NUMBER DEFAULT 1 --輸出不為月份或者日時,當此引數輸入不為1時,返回值為大寫(非漢字)數字
  6. )
  7. RETURN NVARCHAR2
  8. IS
  9. /**
  10. *阿拉伯數字轉化為大寫漢字的函式
  11. *輸入引數轉換前的數字,要保留的小數位數(4舍5入可以不輸入,預設為小數點後2位)
  12. *輸出引數為轉化後的大寫數字
  13. *支援小數點和負數,但數字整數部分不能超過16位
  14. *支援轉換月份和日期,如 SELECT TO_UPPER_NUM('31','3','2') FROM DUAL
  15. *--日期例子(年份的轉換見另一個函式)
  16. * SELECT TO_UPPER_YEAR(TO_CHAR(SYSDATE,'YYYY')) || '年' ||
  17. * TO_UPPER_NUM(TO_CHAR(SYSDATE,'MM'),'2','2') || '月' ||
  18. * TO_UPPER_NUM(TO_CHAR(SYSDATE,'DD'),'2','2') || '日'
  19. * FROM DUAL ;
  20. *--貨幣例子(擷取小數點後兩位,四捨五入)
  21. * SELECT TO_UPPER_NUM(1234.564) FROM dual ;
  22. */
  23. RESULT NVARCHAR2(100) := ''; --返回大寫漢字字串
  24. NUM_ROUND NVARCHAR2(100) := TO_CHAR(ABS(ROUND(P_NUM, P_ROUND))); --轉換數字為小數點後p_round位的字元(正數)
  25. NUM_LEFT NVARCHAR2(100); --小數點左邊的數字
  26. NUM_RIGHT NVARCHAR2(100); --小數點右邊的數字
  27. STR1 NCHAR(10) := '零壹貳叄肆伍陸柒捌玖'; --數字大寫
  28. STR2 NCHAR(16) := '點拾佰仟萬拾佰仟億拾佰仟萬拾佰仟'; --數字位數(從低至高)
  29. STR3 NCHAR(10) := '〇一二三四五六七八九'; --月份數字大寫
  30. STR4 NCHAR(16) := '點十佰仟萬拾佰仟億拾佰仟萬拾佰仟'; --數字位數(從低至高)
  31. NUM_PRE NUMBER(1) := 1; --前一位上的數字
  32. NUM_CURRENT NUMBER(1); --當前位上的數字
  33. NUM_COUNT NUMBER := 0; --當前數字位數
  34. BEGIN
  35. --轉換數字為NULL時,返回NULL
  36. IF P_NUM IS NULL THEN
  37. RETURN NULL;
  38. END IF;
  39. --如果要轉換月份或者日時,則替換臨時變數
  40. IF P_MONTH <> 1 THEN
  41. STR1 := STR3;
  42. STR2 := STR4;
  43. END IF;
  44. --取得小數點左邊的數字
  45. SELECT TO_CHAR(NVL(SUBSTR(TO_CHAR(NUM_ROUND),
  46. 1,
  47. DECODE(INSTR(TO_CHAR(NUM_ROUND), '.'),
  48. 0,
  49. LENGTH(NUM_ROUND),
  50. INSTR(TO_CHAR(NUM_ROUND), '.') - 1)),
  51. 0))
  52. INTO NUM_LEFT
  53. FROM DUAL;
  54. --取得小數點右邊的數字
  55. SELECT SUBSTR(TO_CHAR(NUM_ROUND),
  56. DECODE(INSTR(TO_CHAR(NUM_ROUND), '.'),
  57. 0,
  58. LENGTH(NUM_ROUND) + 1,
  59. INSTR(TO_CHAR(NUM_ROUND), '.') + 1),
  60. P_ROUND)
  61. INTO NUM_RIGHT
  62. FROM DUAL;
  63. --數字整數部分超過16位時.採用從低至高的演算法,先處理小數點左邊的數字
  64. IF LENGTH(NUM_LEFT) > 16 THEN
  65. RETURN '**********';
  66. END IF;
  67. FOR I IN REVERSE 1 .. LENGTH(NUM_LEFT) LOOP
  68. --(從低至高)
  69. NUM_CURRENT := TO_NUMBER(SUBSTR(NUM_LEFT, I, 1)); --當前位上的數字
  70. NUM_COUNT := NUM_COUNT + 1; --當前數字位數
  71. --當前位上數字不為0按正常處理
  72. IF NUM_CURRENT > 0 THEN
  73. --如果轉換數字最高位是十位,轉換後不需要前面的壹,如月份12轉換後為拾貳,則
  74. IF NUM_CURRENT = 1 AND P_MONTH <> 1 AND NUM_COUNT = 2 THEN
  75. RESULT := SUBSTR(STR2, NUM_COUNT, 1) || RESULT;
  76. STR1 := STR3;
  77. ELSE
  78. RESULT := SUBSTR(STR1, NUM_CURRENT + 1, 1)
  79. ||SUBSTR(STR2, NUM_COUNT, 1)
  80. || RESULT;
  81. END IF;
  82. ELSE
  83. --當前位上數字為0
  84. IF MOD(NUM_COUNT - 1, 4) = 0 THEN
  85. --當前位是點、萬或億時
  86. RESULT := SUBSTR(STR2, NUM_COUNT, 1) || RESULT;
  87. NUM_PRE := 0; --點、萬,億前不準加零
  88. END IF;
  89. IF NUM_PRE > 0 OR LENGTH(NUM_LEFT) = 1 THEN
  90. --上一位數字不為0或只有個位時
  91. RESULT := SUBSTR(STR1, NUM_CURRENT + 1, 1) || RESULT;
  92. END IF;
  93. END IF;
  94. NUM_PRE := NUM_CURRENT;
  95. END LOOP;
  96. --再處理小數點右邊的數字
  97. IF LENGTH(NUM_RIGHT) > 0 THEN
  98. FOR I IN 1 .. LENGTH(NUM_RIGHT) LOOP
  99. --(從高至低)
  100. NUM_CURRENT := TO_NUMBER(SUBSTR(NUM_RIGHT, I, 1)); --當前位上的數字
  101. RESULT := RESULT || SUBSTR(STR1, NUM_CURRENT + 1, 1);
  102. END LOOP;
  103. ELSE
  104. RESULT := REPLACE(RESULT, '點', ''); --無小數時去掉點
  105. END IF;
  106. --轉換數字是負數時
  107. IF P_NUM < 0 THEN
  108. RESULT := '負' || RESULT;
  109. END IF;
  110. RETURN RESULT;
  111. EXCEPTION
  112. WHEN OTHERS THEN
  113. DBMS_OUTPUT.PUT_LINE(SQLERRM);
  114. RETURN '';
  115. END;






--