不同客戶對金額小數位處理規則不一:有的精確到元、角、分;尾數處理有「四捨五入」、「全捨(無條件捨去)」、「全入(無條件進位)」。需建立可配置的統一處理函數。
CREATE TABLE rounding_rules (
rule_id NUMBER(1) PRIMARY KEY, -- 規則 ID
amount_dot NUMBER(4,2) DEFAULT 0.01, -- 精度:1=元, 0.1=角, 0.01=分
rounding_mode NUMBER(1) -- 9=全捨, 0=全入, 4=四捨五入
);
CREATE OR REPLACE FUNCTION get_real_amount (
p_rule_id IN NUMBER,
p_amount IN NUMBER
) RETURN NUMBER IS
v_amount_dot VARCHAR2(5);
v_keep NUMBER;
v_rounding NUMBER;
v_result NUMBER := 0;
BEGIN
-- 讀取規則
SELECT amount_dot, NVL(rounding_mode, 0)
INTO v_amount_dot, v_rounding
FROM rounding_rules
WHERE rule_id = p_rule_id;
-- 計算保留小數位數(如 0.01 → 2 位)
v_keep := LENGTH(v_amount_dot) - INSTR(v_amount_dot, '.');
-- 全捨(無條件捨去)
IF v_rounding = 9 THEN
v_result := TRUNC(p_amount, v_keep);
END IF;
-- 四捨五入
IF v_rounding = 4 THEN
v_result := ROUND(p_amount, v_keep);
END IF;
-- 全入(無條件進位)
IF v_rounding = 0 THEN
v_result := TRUNC(p_amount, v_keep);
-- 若截斷後不等於原值,進一個精度單位
IF v_result <> p_amount THEN
v_result := v_result + TO_NUMBER(v_amount_dot);
END IF;
END IF;
RETURN v_result;
EXCEPTION
WHEN OTHERS THEN RETURN p_amount; -- 異常時回傳原值
END get_real_amount;
/
-- 規則:精確到分(0.01),四捨五入(4)
INSERT INTO rounding_rules VALUES (1, 0.01, 4);
SELECT get_real_amount(1, 123.456) FROM dual; -- 123.46
SELECT get_real_amount(1, 123.454) FROM dual; -- 123.45
-- 規則:精確到角(0.1),全入(0)
INSERT INTO rounding_rules VALUES (2, 0.1, 0);
SELECT get_real_amount(2, 123.41) FROM dual; -- 123.5
amount_dot 字串長度推算保留位數,避免硬編碼。TRUNC 作為基礎操作,配合條件判斷實現三種模式。