首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 巧用 ADO 執行 SQL 運算式求值:無需解析器即可計算算術/函數運算式

     編輯:Delphi

前言

需要在 Delphi 中計算字串形式的數學運算式 (如 '123+34*11'、'SQRT(POWER(2,10))')?無需撰寫解析器或引入腳本引擎,利用 ADO 的 SELECT <運算式> 特性,讓資料庫引擎替你算好。本文展示這個「另類」且實用的技巧。

核心原理

大多數 SQL 資料庫 (Access、SQL Server、SQLite、Firebird、Oracle、PostgreSQL) 允許 SELECT 後直接跟純量運算式,不需 FROM 子句。ADO TADOQuery 執行後,結果集第一欄即為運算結果。

最小實作範例

uses ADODB;

function EvalExpression(const Expr: string; ADOConn: TADOConnection): Variant;
var
  Qry: TADOQuery;
begin
  Qry := TADOQuery.Create(nil);
  try
    Qry.Connection := ADOConn;
    Qry.SQL.Text := 'SELECT ' + Expr; // 直接拼接運算式
    Qry.Open;
    if not Qry.IsEmpty then
      Result := Qry.Fields[0].Value
    else
      Result := Null;
  finally
    Qry.Free;
  end;
end;

// 使用範例
var
  Conn: TADOConnection;
  Val: Variant;
begin
  Conn := TADOConnection.Create(nil);
  try
    Conn.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Test.mdb;';
    Conn.LoginPrompt := False;
    Conn.Open;
    
    Val := EvalExpression('123+34*11', Conn);        // 497
    Val := EvalExpression('SQRT(144)', Conn);        // 12 (Access 函數)
    Val := EvalExpression('IIF(1>0, "Yes", "No")', Conn); // "Yes" (Access 立即函數)
  finally
    Conn.Free;
  end;
end;

支援運算式類型對照

類別範例備註
算術運算123+34*11, (5+3)*2標準運算子優先序
數學函數SQRT(16), LOG(10), SIN(PI()/2)依資料庫引擎支援度
字串函數UCASE('hello'), LEFT('abcde',3)Access: UCASE/LEFT/MID/LEN
日期時間DATE(), DATEADD('d',7,NOW())Access: DATE/NOW/DATEADD
條件邏輯IIF(Score>=60,'Pass','Fail')Access 專有 IIF
轉換函數CINT('123'), CDBL(3.14)Access: CINT/CDBL/CCUR

進階:自訂函數註冊 (Access VBA / SQL Server CLR)

若內建函數不足,可在資料庫端定義使用者自訂函數 (UDF):

' Access VBA 模組
Public Function MyFactorial(ByVal n As Long) As Double
  Dim i As Long, r As Double
  r = 1
  For i = 2 To n: r = r * i: Next
  MyFactorial = r
End Function
// Delphi 呼叫
Val := EvalExpression('MyFactorial(5)', Conn); // 120

效能與安全性考量

面向分析建議
效能每次呼叫需 Round-trip 到資料庫引擎,約 1-5ms批次計算時用單一 Query 多行 UNION ALL SELECT ...;高頻計算改用本地解析器
SQL 注入直接拼接使用者輸入極度危險嚴格驗證輸入字元集 (僅允許數字、運算子、函數名白名單);或使用參數化查詢 (但運算式本身難參數化)
資料庫相依函數名、語法因引擎而異封裝介面隔離引擎差異;單元測試覆蓋目標資料庫
連線開銷頻繁開關連線慢共用長連線 TADOConnection;連線池

適用場景與替代方案比較

方案優點缺點適用場景
ADO SELECT (本文)零程式碼解析、支援資料庫函數、利用現有連線需資料庫連線、效能較低、注入風險報表運算式、動態公式配置、偶發計算
Expression Evaluator 元件 (如 EvalExpress)純本地、高效能、語法可控需第三方元件、函數庫有限即時試算表、規則引擎
Pascal Script / DWScript完整腳本語言、支援變數/流程控制整合複雜、體積大使用者自訂邏輯、插件系統
自寫遞迴下降解析器完全控制、無依賴開發成本高、易出錯教學、極簡專案

結語

「用資料庫算數學」是一個巧妙的 Side-effect 應用。在已有 ADO 連線的專案中,臨時需要計算動態運算式時,這招能立即解決問題。但請記住:嚴格輸入驗證與效能評估是上線前必做功課。對於核心業務高頻計算,請投資正規解析器或腳本引擎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved