首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 實作中文大寫金額轉換函數

     編輯:關於SqlServer

前言

在財務系統開發中,將數字金額轉換為中文大寫格式(如「壹佰貳拾叁元整」)是常見需求。雖然 Oracle 資料庫有現成函數,但 SQL Server 內建並無此功能。本文將分享一個從 Oracle 移植而來的 T-SQL 純量值函數 dbo.L2U,能將 numeric(15,2) 金額轉為符合會計習慣的大寫字串。

函數簽名與參數說明

CREATE FUNCTION dbo.L2U (
    @n_LowerMoney numeric(15,2),  -- 小寫金額,支援至兆級、兩位小數
    @v_TransType  int             -- 轉換模式:0=語意轉換(含「整」、「零」處理),1=直譯模式
) RETURNS varchar(200)

核心演算法邏輯

  1. 字串預處理:使用 ROUND 四捨五入至兩位小數,並 LTRIM/RTRIM 移除空白。
  2. 反向逐字元掃描:從字串尾端(分位)向前迴圈,依位數對應中文數字(零~玖)與單位(分、角、元、拾、佰、仟、萬、億)。
  3. 語意修飾(@v_TransType = 0):迴圈結束後,透過多層 REPLACE 清理冗餘「零」、合併單位(如「零角零分」→「整」、「零億零萬零元」→「億元」),並處理「壹元以下」開頭字元修剪。
  4. 回傳結果:最終輸出符合財務憑證列印規範的大寫金額字串。

完整函數碼

CREATE FUNCTION dbo.L2U (@n_LowerMoney numeric(15,2), @v_TransType int)
RETURNS VARCHAR(200) AS
BEGIN
    DECLARE @v_LowerStr VARCHAR(200), @v_UpperPart VARCHAR(200), @v_UpperStr VARCHAR(200), @i_I INT;
    SET @v_LowerStr = LTRIM(RTRIM(ROUND(@n_LowerMoney,2)));
    SET @i_I = 1;
    SET @v_UpperStr = '';

    WHILE (@i_I <= LEN(@v_LowerStr))
    BEGIN
        SELECT @v_UpperPart = 
            CASE SUBSTRING(@v_LowerStr, LEN(@v_LowerStr) - @i_I + 1, 1)
                WHEN '.' THEN '元'
                WHEN '0' THEN '零'
                WHEN '1' THEN '壹'
                WHEN '2' THEN '貳'
                WHEN '3' THEN '參'
                WHEN '4' THEN '肆'
                WHEN '5' THEN '伍'
                WHEN '6' THEN '陸'
                WHEN '7' THEN '柒'
                WHEN '8' THEN '捌'
                WHEN '9' THEN '玖'
            END
            +
            CASE @i_I
                WHEN 1 THEN '分'
                WHEN 2 THEN '角'
                WHEN 3 THEN '元'
                WHEN 4 THEN '拾'
                WHEN 5 THEN '佰'
                WHEN 6 THEN '仟'
                WHEN 7 THEN '萬'
                WHEN 8 THEN '拾'
                WHEN 9 THEN '佰'
                WHEN 10 THEN '仟'
                WHEN 11 THEN '億'
                WHEN 12 THEN '拾'
                WHEN 13 THEN '佰'
                WHEN 14 THEN '仟'
                WHEN 15 THEN '萬'
                ELSE ''
            END;
        SET @v_UpperStr = @v_UpperPart + @v_UpperStr;
        SET @i_I = @i_I + 1;
    END

    IF (0 = @v_TransType)
    BEGIN
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零拾', '零');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零佰', '零');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零仟', '零');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零零零', '零');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零零', '零');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零角零分', '整');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零分', '整');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零角', '零');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零億零萬零元', '億元');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '億零萬零元', '億元');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零億零萬', '億');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零萬零元', '萬元');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '萬零元', '萬元');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零億', '億');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零萬', '萬');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零元', '元');
        SET @v_UpperStr = REPLACE(@v_UpperStr, '零零', '零');
    END

    -- 處理小於 1 元的開頭字元
    IF ('元' = SUBSTRING(@v_UpperStr, 1, 1)) SET @v_UpperStr = SUBSTRING(@v_UpperStr, 2, LEN(@v_UpperStr) - 1);
    IF ('零' = SUBSTRING(@v_UpperStr, 1, 1)) SET @v_UpperStr = SUBSTRING(@v_UpperStr, 2, LEN(@v_UpperStr) - 1);
    IF ('角' = SUBSTRING(@v_UpperStr, 1, 1)) SET @v_UpperStr = SUBSTRING(@v_UpperStr, 2, LEN(@v_UpperStr) - 1);
    IF ('分' = SUBSTRING(@v_UpperStr, 1, 1)) SET @v_UpperStr = SUBSTRING(@v_UpperStr, 2, LEN(@v_UpperStr) - 1);
    IF ('整' = SUBSTRING(@v_UpperStr, 1, 1)) SET @v_UpperStr = '零元整';

    RETURN @v_UpperStr;
END

使用範例

-- 語意模式(推薦)
SELECT dbo.L2U(56588441.111, 0);  -- 輸出:伍仟陸佰伍拾捌萬捌仟肆佰肆拾壹元壹角壹分
SELECT dbo.L2U(0.00, 0);          -- 輸出:零元整

-- 直譯模式
SELECT dbo.L2U(123.45, 1);        -- 輸出:壹佰貳拾參元肆角伍分

注意事項與擴充建議

  • 函數支援最大 999,999,999,999.99(兆級),超過範圍請擴充 numeric 精度與單位邏輯。
  • 若需支援負數,可於函數開頭判斷正負號並加上「負」字前綴。
  • 效能考量:單筆轉換耗時極短,但大批量資料建議在應用層或 CLR 函數處理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved