資料庫開發中常需處理不同進制間的轉換(十六進制 ↔ 十進制、二進制 ↔ 十進制、八進制等)。Oracle 提供豐富的內建函數,並支援自訂函數擴展任意進制轉換。本文系統整理各種轉換方法與效能考量。
TO_NUMBERSELECT TO_NUMBER('19F', 'XXX') FROM dual; -- 415
SELECT TO_NUMBER('F', 'XX') FROM dual; -- 15
SELECT TO_NUMBER('FF', 'XX') FROM dual; -- 255
格式模型:X 代表一位十六進制數字,大小寫不敏感。位數需足夠容納輸入值,否則回傳 ORA-01722。
TO_CHARSELECT TO_CHAR(123, 'XXX') FROM dual; -- 7B
SELECT TO_CHAR(4567, 'XXXX') FROM dual; -- 11D7
SELECT TO_CHAR(255, 'FMXX') FROM dual; -- FF (FM 移除前導空白)
注意:TO_CHAR 預設回傳大寫,若需小寫可用 LOWER() 包裹。
BIN_TO_NUM (9i+)SELECT BIN_TO_NUM(1,1,0,1) FROM dual; -- 13 (1101₂)
SELECT BIN_TO_NUM(1,1,1,0,1) FROM dual; -- 29 (11101₂)
SELECT BIN_TO_NUM(1,0) FROM dual; -- 2 (10₂)
參數:每個位元為獨立參數(0 或 1),最多 255 位元(對應 NUMBER 精度)。高位在前,低位在後。
TO_BASE (十進制 → 任意進制 2~16)CREATE OR REPLACE FUNCTION to_base (
p_dec IN NUMBER,
p_base IN NUMBER
) RETURN VARCHAR2 IS
l_str VARCHAR2(255) DEFAULT NULL;
l_num NUMBER DEFAULT p_dec;
l_hex VARCHAR2(16) DEFAULT '0123456789ABCDEF';
BEGIN
IF TRUNC(p_dec) != p_dec OR p_dec < 0 THEN
RAISE PROGRAM_ERROR; -- 僅支援非負整數
END IF;
LOOP
l_str := SUBSTR(l_hex, MOD(l_num, p_base) + 1, 1) || l_str;
l_num := TRUNC(l_num / p_base);
EXIT WHEN l_num = 0;
END LOOP;
RETURN l_str;
END to_base;
/
SHOW ERRORS
TO_DEC (任意進制 2~16 → 十進制)CREATE OR REPLACE FUNCTION to_dec (
p_str IN VARCHAR2,
p_from_base IN NUMBER DEFAULT 16
) RETURN NUMBER IS
l_num NUMBER DEFAULT 0;
l_hex VARCHAR2(16) DEFAULT '0123456789ABCDEF';
BEGIN
FOR i IN 1 .. LENGTH(p_str) LOOP
l_num := l_num * p_from_base +
INSTR(l_hex, UPPER(SUBSTR(p_str, i, 1))) - 1;
END LOOP;
RETURN l_num;
END to_dec;
/
SHOW ERRORS
CREATE OR REPLACE FUNCTION to_hex (p_dec IN NUMBER) RETURN VARCHAR2 IS
BEGIN RETURN to_base(p_dec, 16); END to_hex;
/
CREATE OR REPLACE FUNCTION to_bin (p_dec IN NUMBER) RETURN VARCHAR2 IS
BEGIN RETURN to_base(p_dec, 2); END to_bin;
/
CREATE OR REPLACE FUNCTION to_oct (p_dec IN NUMBER) RETURN VARCHAR2 IS
BEGIN RETURN to_base(p_dec, 8); END to_oct;
/
-- 十進制 255 轉各進制
SELECT to_hex(255) AS hex, to_bin(255) AS bin, to_oct(255) AS oct FROM dual;
-- HEX: FF, BIN: 11111111, OCT: 377
-- 反向驗證
SELECT to_dec('FF', 16) AS dec16,
to_dec('11111111', 2) AS dec2,
to_dec('377', 8) AS dec8 FROM dual;
-- 全部回傳 255
-- 內建函數交叉驗證
SELECT TO_NUMBER(to_hex(4095), 'XXXX') AS check_hex,
BIN_TO_NUM(1,1,1,1,1,1,1,1,1,1,1,1) AS check_bin
FROM dual; -- 4095, 4095
| 方法 | 適用範圍 | 效能 | 限制 |
|---|---|---|---|
| TO_NUMBER/TO_CHAR | 16↔10 進制 | 極高(原生 C 實作) | 僅 16 進制 |
| BIN_TO_NUM | 2→10 進制 | 高(原生) | 參數列表長度受限,不適合長二進制字串 |
| 自訂 PL/SQL 函數 | 2~16 任意進制雙向 | 中(PL/SQL 迴圈) | 僅支援非負整數;大數值需注意 VARCHAR2 長度 |
若需支援:
TO_BASE 開頭判斷正負號,轉換絕對值後加回符號;l_hex 字元集至 32/64 字元(RFC 4648 標準字母表),邏輯不變。Oracle 內建 TO_NUMBER/TO_CHAR 處理 16 進制、BIN_TO_NUM 處理二進制,已滿足 90% 場景。自訂 TO_BASE/TO_DEC 函數組合則提供 2~16 進制通用解決方案,程式碼精簡、易維護。實務建議:將這組函數封裝為 PKG_BASE_CONV 套件部署於共用 Schema,供全系統呼叫,避免重複造輪子。