Oracle 8i 引入外部程序機制,允許 PL/SQL 呼叫 C/Java 外部函數;在 Windows 平台上,更進一步支援透過 COM 自動化介面操作 Office 應用程式。本文完整記錄從監聽器配置、tnsnames 設定、外部程序驗證,到 COM 介面函數說明、資料型別對應、Excel 自動化實戰範例的端到端實作流程。
extproc 進程extproc 動態載入共享庫 (Windows: DLL)路徑:%ORACLE_HOME%\network\admin\listener.ora
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = CHANET)(PORT = 1521))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = extproc1))
)
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = D:\Oracle\ora92)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = ORADB)
(ORACLE_HOME = D:\Oracle\ora92)
(SID_NAME = ORADB)
)
)
路徑:%ORACLE_HOME%\network\admin\tnsnames.ora
EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
)
(CONNECT_DATA =
(SID = PLSExtProc)
(PRESENTATION = RO)
)
)
一致性檢查:KEY 與 SID 必須與 listener.ora 完全一致。
-- 1. 重啟監聽器
LSNRCTL> STOP
LSNRCTL> START
-- 2. 測試連線
C:\> tnsping EXTPROC_CONNECTION_DATA
-- 預期:OK (30 msec)
-- 3. 直接測試 extproc
D:\Oracle\ora92\bin> extproc
-- 預期:Heterogeneous Agent Release 9.2.0.1.0 - Production
Oracle 提供 ORDCOM 套件封裝 COM 操作,核心函數如下:
| 函數 | 功能 |
|---|---|
| CreateObject | 建立 COM 物件實例 (ProgID 或 CLSID) |
| DestroyObject | 釋放 COM 物件 |
| GetLastError | 取得最後錯誤訊息 |
| GetProperty | 取得屬性值 |
| SetProperty | 設定屬性值 |
| InitArg | 初始化 Invoke 參數 |
| InitOutArg | 初始化輸出參數 |
| GetArg | 取得輸出參數值 |
| SetArg | 設定 Invoke 輸入參數 |
| Invoke | 呼叫方法/屬性存取器 |
| PL/SQL | COM (Variant) |
|---|---|
| VARCHAR2 | BSTR |
| BOOLEAN | BOOL |
| BINARY_INTEGER | BYTE, INT, LONG |
| DOUBLE PRECISION | DOUBLE, FLOAT, CURRENCY |
| DATE | DATE |
-- 1. 建立用戶並授權
CONNECT SYSTEM/chanet@oradb
CREATE USER chanet IDENTIFIED BY chanet;
GRANT CREATE LIBRARY TO chanet;
-- 2. 執行 Oracle 內建 COM 包裝腳本
CONNECT chanet/chanet@oradb
@D:\Oracle\ora92\com\comwrap.sql
STARTUP_WAIT_TIME_LISTENER = 0
CONNECT_TIMEOUT_LISTENER = 10
TRACE_LEVEL_LISTENER = OFF
PASSWORDS_LISTENER = (Oracle)
DECLARE
v_app BINARY_INTEGER; -- Application 物件控制代碼
v_wb BINARY_INTEGER; -- Workbook
v_ws BINARY_INTEGER; -- Worksheet
v_range BINARY_INTEGER; -- Range
v_font BINARY_INTEGER; -- Font
v_token BINARY_INTEGER; -- Invoke token
BEGIN
-- 1. 建立 Excel Application
ORDCOM.CreateObject('Excel.Application', 0, NULL, v_app);
ORDCOM.SetProperty(v_app, 'Visible', 0, FALSE); -- 背景執行
-- 2. 新增 Workbook
ORDCOM.InitArg;
ORDCOM.Invoke(v_app, 'Workbooks.Add', v_token);
ORDCOM.GetArg(v_token, 1, v_wb);
-- 3. 取得 ActiveSheet
ORDCOM.GetProperty(v_wb, 'ActiveSheet', v_ws);
-- 4. 寫入標題列 (Range A1:C1)
ORDCOM.GetProperty(v_ws, 'Range("A1:C1")', v_range);
ORDCOM.SetProperty(v_range, 'Value', 0, 'ID,Name,Salary');
ORDCOM.GetProperty(v_range, 'Font', v_font);
ORDCOM.SetProperty(v_font, 'Bold', 0, TRUE);
ORDCOM.SetProperty(v_font, 'Size', 0, 12);
-- 5. 迴圈寫入資料列 (略,需游標查詢)
-- 6. 儲存並關閉
ORDCOM.InitArg;
ORDCOM.SetArg(v_token, 1, 'D:\export.xls', 'BSTR');
ORDCOM.Invoke(v_wb, 'SaveAs', v_token);
ORDCOM.Invoke(v_app, 'Quit', v_token);
-- 7. 釋放物件
ORDCOM.DestroyObject(v_app);
EXCEPTION
WHEN OTHERS THEN
ORDCOM.GetLastError;
RAISE;
END;
UTL_FILE 產生 CSV 或 XML PublisherDestroyObjectAPEX、ORDS、SQL Developer 匯出功能PL/SQL 呼叫 COM 開啟了資料庫與 Windows 生態整合的大門,特別是 Office 自動化報表場景極具實務價值。但架構複雜度高(監聽器、extproc、DLL、COM、Excel 進程),部署維護成本不容小覷。現代架構建議將報表產出移至應用層或專用報表服務,資料庫專注於資料處理。若必須在資料庫層實作,請嚴格遵循配置驗證流程、建立完善監控告警、並評估無介面替代方案(如 LibreOffice UNO、Python openpyxl 透過外部程序)。