SQLFileManager 是一個將 SQL 查詢從程式碼中分離出來,獨立管理的工具。以下展示導入此工具前後的差異比較,幫助您了解其價值。
📢 實施策略: 未來所有新增或修改的程式將採用 SQLFileManager 架構。針對使用者經常反映問題的現有程式也將優先改用此方法,特別是報表相關功能將獲得最顯著的改善。
⏱️ 投資效益說明: 短期內可能看不出明顯效益,但在處理BUG錯誤和單純新增欄位時將大幅提升效率。如SBAAA補助條件+SBBX補助報表的開發時間雖從原估7天拉長到14天,但能大幅縮短後續維護時間,長期投資回報顯著。
Project/ ├── Unit1.pas (含SQL) ├── Unit2.pas (含SQL) ├── FormReport.pas (含SQL) └── DataModule.pas (含SQL)
Project/ ├── Unit1.pas ├── Unit2.pas ├── FormReport.pas ├── DataModule.pas ├── SQL/ │ ├── 補助報表/ │ │ ├── truncate_sbbx_tmp.sql │ │ ├── insert_sbaaa_data.sql │ │ └── get_subsidy_data.sql │ └── 共用/ │ └── common_header.sql └── Reports/ └── SBBXrpt.fr3 (FastReport報表檔)
採用 SQLFileManager 後,報表相關功能將獲得最直接的效益:
.sql
檔案與 FastReport 報表檔,無需變更程式碼procedure TfrmSBBX.ReportProcess(nType: Integer; const SubsidyTableName: string): Integer;
var
sVenn, sVenn1, sVenn2, sVenn3, sVenn5, sVenn6, sVenn8, sVenn9, sVenn10: string;
sItno, sEndDateCondition, sVendorFilter, sExcludeFilter: string;
begin
// ... 其他代碼 ...
// 獲取報表資料 - SQL直接寫在程式碼中
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add('SELECT a.vditno AS 品項代號, a.vdnr AS 品項名稱,');
Query1.SQL.Add(' a.vcqty1+a.vcqty2 AS 銷售數量,');
Query1.SQL.Add(' a.vcqty1+a.vcqty2 AS 補助數量,');
Query1.SQL.Add(' a.vcup21 AS 單價,');
Query1.SQL.Add(' a.vcup21 * (a.vcqty1+a.vcqty2) AS 補助金額,');
Query1.SQL.Add(' a.vcdat1 AS 起始日期, a.vcdat2 AS 結束日期,');
Query1.SQL.Add(' c.aaname AS 補助說明');
Query1.SQL.Add('FROM vccs a, sbaaa c');
Query1.SQL.Add('WHERE a.vcpmno = c.aapmno');
Query1.SQL.Add(' AND a.vcpmno = :qpmno1');
Query1.SQL.Add(' AND a.vcvenn = :qvenn');
// 添加條件
if sItno <> '' then
Query1.SQL.Add(sItno);
if sVenn <> '' then
Query1.SQL.Add(sVenn);
if SubsidyTableName = 'SBAAA' then
Query1.SQL.Add(' AND AAABGDT >= :qyymm');
Query1.SQL.Add('ORDER BY a.vditno');
// 設置參數值
Query1.ParamByName('qpmno1').AsString := Edyymm.Text + Edpmno.Text;
Query1.ParamByName('qvenn').AsString := sVenn8;
Query1.ParamByName('qyymm').AsString := Edyymm.Text;
Query1.Open;
// ... 其他代碼 ...
end;
procedure TfrmSBBX.ReportProcess(nType: Integer; const SubsidyTableName: string): Integer;
var
sVenn, sVenn1, sVenn2, sVenn3, sVenn5, sVenn6, sVenn8, sVenn9, sVenn10: string;
sItno, sEndDateCondition, sVendorFilter, sExcludeFilter: string;
varMap: TDictionary<string, string>;
begin
// ... 其他代碼 ...
varMap := TDictionary<string, string>.Create;
try
// 設定變數
varMap.Add('ITEM_FILTER', sItno);
varMap.Add('VENDOR_FILTER', sVenn);
varMap.Add('END_DATE_CONDITION', sEndDateCondition);
// 從外部檔案讀取SQL並執行
SQLManager.Select(QueryRpt, '補助報表', 'get_subsidy_data',
['qpmno1', 'qpmno', 'qyymm', 'qvenn'],
[Edyymm.Text + Edpmno.Text, Edpmno.Text, Edyymm.Text, sVenn8],
varMap);
// ... 其他代碼 ...
finally
varMap.Free;
end;
end;
-- 檔案: SQL/補助報表/get_subsidy_data.sql
-- INCLUDE: 共用/common_header
-- 業務邏輯:
-- 本查詢用於獲取經銷商的補助報表數據
-- 包含品項銷售數量、補助金額等關鍵資訊
SELECT
a.vditno AS 品項代號,
a.vdnr AS 品項名稱,
a.vcqty1+a.vcqty2 AS 銷售數量,
a.vcqty1+a.vcqty2 AS 補助數量,
a.vcup21 AS 單價,
a.vcup21 * (a.vcqty1+a.vcqty2) AS 補助金額,
a.vcdat1 AS 起始日期,
a.vcdat2 AS 結束日期,
c.aaname AS 補助說明
FROM
vccs a
JOIN
sbaaa c ON a.vcpmno = c.aapmno
WHERE
a.vcpmno = :qpmno1
AND a.vcvenn = :qvenn
${ITEM_FILTER}
${VENDOR_FILTER}
${END_DATE_CONDITION}
ORDER BY
a.vditno
⚡ 錯誤診斷與修正範例:
當 SQL 執行發生錯誤時,新版 SQLFileManager 會顯示詳細錯誤訊息:
技術人員可直接在修改 SQL 檔案並立即測試,無需等待程式重新編譯發布。
比較項目 | 導入前 | 導入後 |
---|---|---|
SQL 管理方式 | 分散在程式碼中 | 集中在外部 .sql 檔案中 |
報表欄位修改流程 | 修改程式碼 → 重新編譯 → 部署 | 修改 .sql 檔案 + FastReport → 部署(不需重編譯) |
BUG修復時間 | 數天(需重編程序) | 數小時(直接修改SQL) |
問題處理時間 | 數小時至數天(需返回開發環境) | 數分鐘至數小時(可直接修改) |
錯誤診斷能力 | 有限(基本錯誤訊息) | 強大(詳細錯誤資訊與日誌) |
SQL 重用性 | 低(需複製貼上代碼) | 高(支援 INCLUDE 引用) |
變數替換 | 手動拼接 SQL 字串 | 使用 ${變數名} 自動替換 |
程式碼可讀性 | 較差(SQL 與邏輯混合) | 較佳(邏輯清晰) |
文檔化程度 | 低(SQL 註解經常被忽略) | 高(支援業務邏輯說明與搜尋) |
效能優化 | 無內建機制 | 內建快取機制與慢查詢日誌 |
項目 | 初期投入 | 長期效益 |
---|---|---|
開發時間 | 增加 100%(如:7天 → 14天) | 後續維護時間縮短 70% |
錯誤處理 | 前期建置錯誤診斷機制 | BUG修復時間縮短 80% |
經銷商滿意度 | 短期影響不明顯 | 問題解決速度提升,經銷商滿意度大幅提高 |
報表修改 | 報表機制改造投入 | 後續修改時間縮短 85%,可直接完成 |
投資回報期 | 預估在5-7個報表功能或3-4次重大BUG修復後即可回收初期投入 |
總結:SQLFileManager 導入雖然初期需要額外投入時間(如SBAAA補助條件+SBBX補助報表由7天增加到14天),但後續在BUG修復、報表修改與問題處理方面的顯著效益將快速收回投資。隨著使用範圍的擴大,這種架構將為系統帶來長期的健康性與靈活性,讓我們能更快回應經銷商需求變化。