UTL_INADDR 是 Oracle 提供的網路工具套件,用於在 PL/SQL 中解析**主機名 ↔ IP 位址**,支援本機、區域網路與網際網路環境。
需求權限:`EXECUTE ON UTL_INADDR` (通常授予 PUBLIC)
網路前提:資料庫伺服器具備 DNS 解析能力 / hosts 檔配置正確
-- 語法
UTL_INADDR.GET_HOST_ADDRESS(host VARCHAR2 DEFAULT NULL) RETURN VARCHAR2
-- 參數為 NULL 時解析本機
-- 失敗拋出例外 (如 ORA-29257: host unknown)
| 需求 | SQL 語句 | 回傳範例 |
|---|---|---|
| 查詢網域 IP | SELECT UTL_INADDR.GET_HOST_ADDRESS('www.qq.com') FROM dual; | 112.80.248.76 |
| 查詢本機 IP | SELECT UTL_INADDR.GET_HOST_ADDRESS() FROM dual; | 192.168.1.100 |
| 查詢區域網主機名 IP | SELECT UTL_INADDR.GET_HOST_ADDRESS('yuechu') FROM dual; | 192.168.0.156 |
-- 語法
UTL_INADDR.GET_HOST_NAME(ip VARCHAR2 DEFAULT NULL) RETURN VARCHAR2
-- 參數為 NULL 時解析本機主機名
| 需求 | SQL 語句 | 回傳範例 |
|---|---|---|
| 查詢本機主機名 | SELECT UTL_INADDR.GET_HOST_NAME() FROM dual; | db-server-01 |
| 反解區域網 IP 對應主機名 | SELECT UTL_INADDR.GET_HOST_NAME('192.168.0.156') FROM dual; | yuechu |
| 反解網際網路 IP 對應域名 | SELECT UTL_INADDR.GET_HOST_NAME('219.153.50.84') FROM dual; | www.example.com |
CREATE OR REPLACE TRIGGER audit_logon_trg
AFTER LOGON ON DATABASE
DECLARE
v_client_ip VARCHAR2(45);
v_host_name VARCHAR2(255);
BEGIN
-- 從 SYS_CONTEXT 取得客戶端 IP (需啟用 SQLNET.ORA: SQLNET.AUTHENTICATION_SERVICES=(NTS))
v_client_ip := SYS_CONTEXT('USERENV', 'IP_ADDRESS');
-- 若為 IPv6 或代理 IP,嘗試反解主機名
BEGIN
v_host_name := UTL_INADDR.GET_HOST_NAME(v_client_ip);
EXCEPTION
WHEN OTHERS THEN
v_host_name := 'UNRESOLVED';
END;
INSERT INTO login_audit (username, client_ip, host_name, logon_time)
VALUES (USER, v_client_ip, v_host_name, SYSDATE);
END;
/
CREATE OR REPLACE PROCEDURE check_smtp_reachable(p_host VARCHAR2) IS
v_ip VARCHAR2(45);
BEGIN
v_ip := UTL_INADDR.GET_HOST_ADDRESS(p_host);
DBMS_OUTPUT.PUT_LINE(p_host || ' -> ' || v_ip || ' : DNS 解析正常');
-- 進一步可用 UTL_TCP 嘗試連線埠驗證服務可用性
DECLARE
v_conn UTL_TCP.CONNECTION;
BEGIN
v_conn := UTL_TCP.OPEN_CONNECTION(v_ip, 25);
UTL_TCP.CLOSE_CONNECTION(v_conn);
DBMS_OUTPUT.PUT_LINE('SMTP 埠 25 可連線');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SMTP 埠 25 無法連線: ' || SQLERRM);
END;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('DNS 解析失敗: ' || SQLERRM);
END;
/
-- 根據環境變數動態解析目標主機 IP,避免硬編碼
DECLARE
v_target_host VARCHAR2(100) := 'api.payment-gateway.com';
v_ip VARCHAR2(45);
v_dblink_sql VARCHAR2(500);
BEGIN
v_ip := UTL_INADDR.GET_HOST_ADDRESS(v_target_host);
-- 動態建立/重建 DB Link (需 CREATE DATABASE LINK 權限)
v_dblink_sql := 'CREATE OR REPLACE DATABASE LINK payment_gw
CONNECT TO api_user IDENTIFIED BY secret
USING ''(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST='
|| v_ip || ')(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))''';
EXECUTE IMMEDIATE v_dblink_sql;
DBMS_OUTPUT.PUT_LINE('DB Link 已更新至 IP: ' || v_ip);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('失敗: ' || SQLERRM);
END;
/
| 錯誤代碼 | 原因 | 解決 |
|---|---|---|
| ORA-29257: host unknown | DNS 解析失敗 / hosts 檔無記錄 | 檢查 `/etc/resolv.conf`、DNS 伺服器、防火牆 UDP 53 |
| ORA-24247: network access denied by ACL | 11g+ 預設啟用精細網路 ACL 控制 | 建立 ACL 授權:DBMS_NETWORK_ACL_ADMIN.CREATE_ACL/ADD_PRIVILEGE/ASSIGN_ACL |
| ORA-29260: network error | 網路不通 / 逾時 | ping/telnet 驗證連通性,檢查 MTU/防火牆 |
| 回傳 IPv6 格式 (::ffff:192.168.1.1) | 系統啟用 IPv6,Oracle 回傳映射格式 | 應用層處理或停用 IPv6 (`/etc/sysctl.conf` net.ipv6.conf.all.disable_ipv6=1) |
BEGIN
-- 建立 ACL
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL(
acl => 'utl_inaddr.xml',
description => 'UTL_INADDR Network Access',
principal => 'SCOTT',
is_grant => TRUE,
privilege => 'resolve');
-- 指派給所有主機 (或特定網段)
DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL(
acl => 'utl_inaddr.xml',
host => '*');
COMMIT;
END;
/
UTL_INADDR 是資料庫層網路解析的輕量級工具,善用於審計、動態配置、服務健康檢查等場景,但需注意 11g+ ACL 授權與異常處理。