Oracle中金额数字转换为大写汉字

这个版本的函数,解决的问题

  1. 零出现重复或不出现的问题
  2. 当金额只有角或分的显示问题
  3. 金额为整数时,是否想要带 整 字
sql 复制代码
CREATE OR REPLACE FUNCTION NUM_TO_CAPITAL(MONEY IN NUMBER)
  RETURN VARCHAR2
IS
  TYPE STRING_ARRAY IS TABLE OF VARCHAR2(10);
  DIGIT_STR STRING_ARRAY := STRING_ARRAY('零','壹','贰','叁','肆','伍','陆','柒','捌','玖');
  
  V_NUM        VARCHAR2(100);
  V_INT        VARCHAR2(100);
  V_DEC        VARCHAR2(10);
  V_RESULT     VARCHAR2(300) := '';
  V_SECTION    VARCHAR2(4);
  V_SEC_RES    VARCHAR2(50) := '';
  V_I          NUMBER := 0;
  V_HAS_NUM    BOOLEAN;
  V_IS_OVER_WAN BOOLEAN := FALSE; -- 是否 >= 万元
BEGIN
  -- 1. 空值处理
  IF MONEY IS NULL THEN
    RETURN '';
  END IF;

  -- 2. 负数处理
  IF MONEY < 0 THEN
    RETURN '负' || NUM_TO_CAPITAL(ABS(MONEY));
  END IF;

  -- 3. 金额上限校验
  IF MONEY >= POWER(10,16) THEN
    RAISE_APPLICATION_ERROR(-20001, '金额超出转换范围(最大支持9999999999999999.99)');
  END IF;

  -- 4. 格式化拆分整数、小数
  V_NUM := TO_CHAR(ROUND(MONEY, 2), 'FM9999999999999990.00');
  V_INT := SUBSTR(V_NUM, 1, INSTR(V_NUM, '.') - 1);
  V_DEC := SUBSTR(V_NUM, INSTR(V_NUM, '.') + 1);

  -- 5. 整数部分为0时,不拼接"零元",直接处理小数
  IF V_INT != '0' THEN
    WHILE LENGTH(V_INT) > 0 LOOP
      IF LENGTH(V_INT) > 4 THEN
        V_SECTION := SUBSTR(V_INT, LENGTH(V_INT)-3, 4);
        V_INT     := SUBSTR(V_INT, 1, LENGTH(V_INT)-4);
      ELSE
        V_SECTION := LPAD(V_INT, 4, '0');
        V_INT     := '';
      END IF;

      V_SEC_RES := '';
      V_HAS_NUM := FALSE;

      -- 逐位转换:仟、佰、拾、个
      FOR J IN 1..4 LOOP
        DECLARE
          D  CHAR(1) := SUBSTR(V_SECTION, J, 1);
          U  VARCHAR2(2) := CASE J WHEN 1 THEN '仟' WHEN 2 THEN '佰' WHEN 3 THEN '拾' ELSE '' END;
        BEGIN
          IF D != '0' THEN
            IF V_SEC_RES IS NOT NULL AND SUBSTR(V_SECTION, J-1, 1) = '0' THEN
              V_SEC_RES := V_SEC_RES || '零';
            END IF;
            V_SEC_RES := V_SEC_RES || DIGIT_STR(TO_NUMBER(D)+1) || U;
            V_HAS_NUM := TRUE;
          END IF;
        END;
      END LOOP;

      -- 追加单位:万、亿、万亿
      IF V_HAS_NUM THEN
        CASE V_I
          WHEN 1 THEN 
            V_SEC_RES := V_SEC_RES || '万'; 
            V_IS_OVER_WAN := TRUE;
          WHEN 2 THEN 
            V_SEC_RES := V_SEC_RES || '亿'; 
            V_IS_OVER_WAN := TRUE;
          WHEN 3 THEN 
            V_SEC_RES := V_SEC_RES || '万亿'; 
            V_IS_OVER_WAN := TRUE;
          ELSE NULL;
        END CASE;
        V_RESULT := V_SEC_RES || V_RESULT;
      ELSIF V_I = 1 AND V_RESULT IS NOT NULL THEN
        IF SUBSTR(V_RESULT, 1, 1) != '零' THEN
          V_RESULT := '零' || V_RESULT;
        END IF;
      END IF;

      V_I := V_I + 1;
    END LOOP;

    -- 整数部分收尾
    IF V_RESULT IS NOT NULL THEN
      V_RESULT := V_RESULT || '元';
    END IF;
  END IF;

  -- 6. 小数部分处理
  IF V_DEC != '00' THEN
    -- 角
    IF SUBSTR(V_DEC,1,1) != '0' THEN
      V_RESULT := V_RESULT || DIGIT_STR(TO_NUMBER(SUBSTR(V_DEC,1,1))+1) || '角';
    ELSIF SUBSTR(V_DEC,2,1) != '0' AND V_RESULT IS NOT NULL THEN
      V_RESULT := V_RESULT || '零';
    END IF;
    -- 分
    IF SUBSTR(V_DEC,2,1) != '0' THEN
      V_RESULT := V_RESULT || DIGIT_STR(TO_NUMBER(SUBSTR(V_DEC,2,1))+1) || '分';
    END IF;
  ELSE
    -- 核心规则:只有 ≥ 万元 且无小数时才加"整"
    IF V_RESULT IS NOT NULL AND V_IS_OVER_WAN THEN
      V_RESULT := V_RESULT || '整';
    END IF;
  END IF;

  -- 7. 处理全零金额
  IF V_RESULT IS NULL OR V_RESULT = '' THEN
    RETURN '零元';
  END IF;

  RETURN V_RESULT;
END NUM_TO_CAPITAL;
相关推荐
广州灵眸科技有限公司2 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
Cloud云卷云舒4 小时前
云卷云舒:从Oracle/MySQL迁移到HaishanDB:迁移评估工具核心技术拆解
mysql·oracle·ai-native·haishandb·信创数据库替换
憧憬成为web高手4 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学5 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
oradh6 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
z123456789867 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD7 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关
java_logo8 小时前
Docker Compose 部署 ClickHouse:快速搭建高性能列式数据库
数据库·clickhouse·docker·列式数据库·轩辕镜像·高性能数据库·clickhouse部署教程
TlSfoward8 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php
数智化管理手记9 小时前
账龄分析手工统计易遗漏?自动账龄分析工具怎么搭建
大数据·网络·数据库·人工智能·数据挖掘