Python – Script
在寫全端的專案的時候有遇到一個問題就是Next.js沒辦法跑DB2! ( IBM 公司開發的一款企業級關聯式資料庫管理系統RDBMS,以極高的效能著稱)
因此我的解法是透過 python 寫一個Script,有需要去DB2查詢時就只用指令執行此 python,python腳本回傳JSON即可~
這裡提供範例:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import sys
import io
import json
import os
# --- DB2 環境配置 ---
if os.name == 'nt':
clidriver_path = r'C:\temp\clidriver\bin'
if os.path.exists(clidriver_path):
os.add_dll_directory(clidriver_path)
# 強制 UTF-8 輸出,避免 Windows 轉碼錯誤
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
def _build_conn_string() -> str:
host = os.environ.get("DB2_HOST", "XXX.vghtpe.gov.tw").strip()
port = os.environ.get("DB2_PORT", "3306").strip()
database = os.environ.get("DB2_DATABASE", "DBHIS").strip()
user = os.environ.get("DB2_USER", os.environ.get("DB2_UID", "TEST")).strip()
password = os.environ.get("DB2_PASSWORD", os.environ.get("DB2_PWD", "TEST")).strip()
return f"DATABASE={database};HOSTNAME={host};PORT={port};PROTOCOL=TCPIP;UID={user};PWD={password};"
# 用法: db2_vitals.py <histno> <caseno>
def main():
histno = sys.argv[1].strip()
caseno = sys.argv[2].strip()
try:
import ibm_db
conn = ibm_db.connect(_build_conn_string(), "", "")
sql = """
SELECT
ERTTBP1,
ERTTBP2,
ERTTPR,
ERTTRR,
ERTTBT,
ERTTKG,
ERTTS12
FROM VGHLNXVG.ERTTAS5
WHERE ERTTHIST = ?
AND RIGHT(TRIM(ERTTBKEY), 8) = ?
WITH UR
"""
stmt = ibm_db.prepare(conn, sql)
ibm_db.bind_param(stmt, 1, histno)
ibm_db.bind_param(stmt, 2, caseno)
ibm_db.execute(stmt)
row = ibm_db.fetch_assoc(stmt)
if row:
final_data = {
"bp_s": str(row.get("ERTTBP1") or "").strip(),
"bp_d": str(row.get("ERTTBP2") or "").strip(),
"pr": str(row.get("ERTTPR") or "").strip(),
"rr": str(row.get("ERTTRR") or "").strip(),
"bt": str(row.get("ERTTBT") or "").strip(),
"bw": str(row.get("ERTTKG") or "").strip(),
"疼痛評估": str(row.get("ERTTS12") or "").strip(),
}
print(json.dumps({"success": True, "data": final_data}))
else:
print(json.dumps({"success": False, "error": 123}))
ibm_db.close(conn)
except Exception as e:
# 發生錯誤時輸出詳細資訊到 stderr 並回傳失敗 JSON
import traceback
print(traceback.format_exc(), file=sys.stderr)
print(json.dumps({"success": False, "error": str(e)}))
sys.exit(1)
if __name__ == "__main__":
main()Code language: JavaScript (javascript)
這裡解釋一些比較特殊的寫法以及為什麼要這樣寫:
註:之後有可能會要上Docker因此有些Linux的指令會先留著
標頭
#!/usr/bin/env python3:指定使用 Python 3 解釋器執行。在linux下會被執行。# -*- coding: utf-8 -*-:宣告檔案編碼為 UTF-8,確保中文字元顯示正確。from __future__ import annotations:啟用Type Hints(型別提示):-> str:- 如果函數定義回傳
str,結果回傳數字,IDE 會跟據此偵測錯誤。
- 如果函數定義回傳
import sys, io, json, os:匯入標準函式庫,處理系統參數、輸出流、JSON 格式與作業系統功能。
DB2 環境配置
if os.name == 'nt'::判斷是否在 Windows 環境下。os.add_dll_directory(...):告訴 Windows 哪裡可以找到 DB2 的連接驅動程式(clidriver)。sys.stdout強制將標準輸出 (stdout) 與錯誤輸出 (stderr) 設定為 UTF-8 編碼,防止在 Windows CMD 中出現亂碼。
main
- 連接資料庫:
import ibm_db:在此階段才匯入 DB2 驅動,確保環境設定已完成。ibm_db.connect(...):建立連線。
- 執行 SQL:
- 使用
?佔位符(Parameterized Query),這能有效防止 SQL Injection(資料隱碼攻擊)。 WITH UR:意指 Uncommitted Read,在查詢 DB2 時允許讀取尚未提交的資料,可提升查詢效能且減少鎖定衝突。為DB2特有寫法。- 使用
bind_param寫入資料,資料庫會將user_input視為純粹的「資料(Data)」,而不是「SQL 指令」,防止SQL注入。
- 使用
- 資料處理:
ibm_db.fetch_assoc(stmt):將查詢到的結果轉為關聯式陣列(字典)。- 若有結果,將欄位名稱(如
ERTTBP1)對應到更友善的 JSON Key(如bp_s代表血壓收縮壓)。 json.dumps(...):將結果轉為 JSON 字串輸出。
- 例外處理 (
except):- 若查詢失敗,輸出錯誤堆疊資訊(
traceback)到錯誤流,並輸出 JSON 格式的錯誤訊息,方便呼叫端捕捉失敗狀態。
- 若查詢失敗,輸出錯誤堆疊資訊(
