傳統多條件查詢需程序員為每種組合寫 SQL,或動態拼接字符串極易出錯。用戶界面往往只提供 2-3 個固定條件。本文提出利用 TDBGrid 的 PickList 特性,構建類 Excel 的條件編輯表格,用戶可任意增刪行、選擇字段/操作符/邏輯連接詞,程序自動生成標準 SQL,實現真正的「無限條件、可視化、用戶可微調」查詢。
Table1:數據源表 (如 Customer)Table2 (對應 CxComm.db):條件存儲表,結構:FieldName (字段名), Operator (操作符), Value (值), Logic (AND/OR)DBGrid2:綁定 Table2,設置列 PickList 實現下拉選擇Query1:執行生成的 SQLMemo1:顯示生成的 SQL,允許用戶手工修改 (如加括號調整優先級)procedure TfrmDBGrid.MySetDBGrid(sTable: TTable; tjDBGrid: TDBGrid);
var i: Byte;
begin
if not sTable.Active then sTable.Open;
tjDBGrid.Columns[0].PickList.Clear;
for i := 0 to sTable.FieldCount - 1 do
tjDBGrid.Columns[0].PickList.Add(sTable.Fields[i].FieldName); // 字段名列
tjDBGrid.Columns[1].PickList.Text := '='#13#10'<>'#13#10'>'#13#10'>='#13#10'<'#13#10'<='; // 操作符列
tjDBGrid.Columns[3].PickList.Text := 'AND'#13#10'OR'; // 邏輯列
end;
function TfrmDBGrid.MyCreate_SQL(sTable, tjTable: TTable; tjQuery: TQuery): Boolean;
var i: Byte; lsDate: TDateTime; sLj, sFilter, sFieldName: string;
begin
Result := True;
with tjQuery.SQL do
begin
Close; Clear;
DatabaseName := sTable.DatabaseName;
Add('Select * from ' + sTable.TableName);
end;
with tjTable do
begin
if not Active then Open;
if IsEmpty then begin ShowMessage('未選擇篩選條件!'); Exit; end;
tjQuery.SQL.Add('Where ');
sFilter := ''; First;
for i := 0 to RecordCount - 1 do
begin
sLj := Fields[3].AsString; // Logic (AND/OR)
sFilter := sFilter + '(';
sFilter := sFilter + Fields[0].AsString + Fields[1].AsString; // Field + Operator
sFieldName := Fields[0].AsString;
case sTable.FieldByName(sFieldName).DataType of
ftString: sFilter := sFilter + QuotedStr(Fields[2].AsString); // 字符串加引號
ftFloat, ftAutoInc, ftSmallInt, ftInteger, ftCurrency:
sFilter := sFilter + Fields[2].AsString; // 數值直接拼接
ftDate:
try
lsDate := StrToDate(Fields[2].AsString);
sFilter := sFilter + QuotedStr(FormatDateTime('mm/dd/yyyy', lsDate)); // 日期格式化
except ShowMessage('錯誤的日期格式!'); Result := False; Break; end;
else
// 可擴展其他類型
end;
sFilter := sFilter + ')';
if sLj <> '' then
begin
if RecNo <> RecordCount then sFilter := sFilter + ' ' + sLj + ' '; // 非最後行加邏輯
end else Break;
Next;
end;
tjQuery.SQL.Add(sFilter);
end;
end;
procedure TfrmDBGrid.Button3Click(Sender: TObject);
begin
with Query1, SQL do
begin
Close;
if Memo1.Modified then SQL := Memo1.Lines; // 用戶可能在 Memo 中手改 SQL
try
Open; // 用 Open 而非 ExecSQL,因為是 SELECT
except
MessageBeep(0);
Application.MessageBox('錯誤的 SQL 語句!', '確認', MB_OK + MB_ICONSTOP);
Close;
end;
end;
end;
| 特性 | 傳統固定條件 | 本方案 (DBGrid 條件表) |
|---|---|---|
| 條件數量 | 固定 1-3 個 | 無限制 (表格行數動態增減) |
| 字段選擇 | 預設下拉框 | 自動讀取數據源所有字段 |
| 操作符 | 硬編碼 | 統一配置 (=, <>, >, >=, <, <=) |
| 邏輯組合 | 固定 AND/OR | 每行獨立指定 AND/OR |
| 用戶干預 | 不可見 | Memo 顯示 SQL,可手工加括號/調整 |
| 代碼維護 | 每新增查詢改代碼 | 通用邏輯,零代碼擴展新表 |
Append/Delete),提升易用性。TClientDataSet / TMemTable) 無需物理文件。將「查詢條件」數據化、表格化,利用 DBGrid.PickList 實現可視化編輯,再通用算法生成 SQL,是構建靈活查詢界面的經典模式。此思想不限於 Delphi,同樣適用於 C# DataGridView、Web 前端表格組件等場景。