1) 可选择忽略条件的典型方法是再添加一个“切换”参数。考虑一下这个 Delphi 代码
Result := True; // or False. Actually - some previous part of formula
If Need_Check_Option_A then
Result := Result and ( Option_A > 20 );
If Need_Check_Option_B then
Result := Result and ( Option_B < 10 );
明白了吗?
但是很长就是,有没有更简洁的写法?
Result := .....some other parts....
and (Ignore_Option_A or (Option_A > 20 ))
and (Ignore_Option_B or (Option_A < 10 ))
and ....
现在让我们将它从 Delphi 重新表述为 SQL WHERE 子句
WHERE (.......) and (......)
AND ( ( :Use_pagamento = 0 ) or ( T.INCASSO = :pagamento ) )
AND ( ( :Use_terminale = 0 ) or ( T.TERMINALE = :terminale ) )
无论您是否将 USE_xxxx 参数设置为零(类似于 false),那么第二次检查将是快捷方式,被忽略。
调用代码类似于
FDquery3.ParamByName('data1').AsDate := Datetimepicker1.Date;
FDquery3.ParamByName('data2').AsDate := Datetimepicker2.Date;
FDQuery3.ParamByName('pagamento').AsString := Combobox3.Items [Combobox3.Itemindex];
FDQuery3.ParamByName('terminale').AsString := Combobox5.Items [Combobox5.Itemindex];
FDQuery3.ParamByName('Use_pagamento').AsSmallInt := Ord( CheckBox3.Checked );
FDQuery3.ParamByName('Use_terminale').AsSmallInt := Ord( CheckBox5.Checked );
更多建议如下:
2) 使用像 ComboBox3 这样的名称是不好的。你不会明白它们的意思,它们的目的是什么。看看你的 SQL - 你在那里给名字!你不喜欢
SELECT FIELD1, FIELD2 FROM TABLE1 WHERE FIELD3 < :PARAM1
你也必须给你的 Delphi 对象起合理的名字!
FDQuery3,Checkbox3,Combobox5 - 全部重命名,给它们一些有意义的名字!
3) 你有一个嵌套选择作为Cliente 列。除非非常特殊的情况是缓慢且低效的 - 也将其更改为JOIN(如果有时没有匹配值,可能会更改为LEFT JOIN)
select
G.NUM_PROG,T.DATA,T.ORA,C.DESCRIZIONE,
-- (select DESKEY from ANAFORN where CODKEY=T.CODICE ) as Cliente,
A.DESKEY as Cliente,
O.NOMINATIVO, T.TERMINALE,T.INCASSO
from LG_RIGHE G
inner join LG_TESTA T on G.NUM_PROG =T.NUM_PROG
inner join OPERATORI O on T.OPERATORE = O.CODICE
inner join LG_CAUSA C on T.CAUSALE = C.CODICE
/* left */ join ANAFORN A on A.CODKEY=T.CODICE
where T.DATA >= :data1
and T.DATA <= :data2
AND ( ( :Use_pagamento = 0 ) or ( T.INCASSO = :pagamento ) )
AND ( ( :Use_terminale = 0 ) or ( T.TERMINALE = :terminale ) )
order by G.NUM_PROG
4) 根据具体情况,您可能只想更改 SQL 文本。
如果该参数将被忽略 - 那么只需将其删除!
这个选项不是通用的,但它有好有坏。
但在您的情况下,它宁愿做善事也可能什么都不做 - 因为您需要人工重新打开查询,而人工执行此操作的频率不能超过每秒一次。
很好:然后服务器获取您的 SQL 文本并准备查询计划。如何获取数据的内部程序。而且它还不知道你的参数是什么,所以它准备 PLAN 总是检查这些参数。即使您以后会忽略它们。有时它可能会让服务器选择较慢的 PLAN,如果它知道不会使用该参数,它可以选择较快的 PLAN。有时它没有任何区别。运气游戏。
不好:如果你保持 SQL 文本相同,那么你可以PREPARE 查询一次,当你用不同的参数重新打开查询时,服务器不会构建不同的PLAN。但是,如果您确实更改了 SQL 文本,那么服务器将不得不解析该新查询并再次准备计划,然后才能为您提供数据。有时打开关闭查询会花费相当长的时间,例如每秒 1000 次。当然,当您使用人工设置这些复选框、组合框然后按下按钮时,他不会那么频繁地这样做,所以在这种情况下风险是没有实际意义的。
所以在你的情况下,你可能会做这样的事情而不是引入那些切换参数:
var qt: TStrings; // SQL query text
.....
qt := FDQuery3.SQL;
qt.Clear; // changing SQL Text would auto-close the query
qt.Add('select G.NUM_PROG,T.DATA,T.ORA,C.DESCRIZIONE, ');
qt.Add(' A.DESKEY as Cliente, O.NOMINATIVO, T.TERMINALE,T.INCASSO ');
qt.Add('from LG_RIGHE G ');
qt.Add(' join LG_TESTA T on G.NUM_PROG = T.NUM_PROG ');
qt.Add(' left join ANAFORN A on A.CODKEY=T.CODICE');
qt.Add(' join OPERATORI O on T.OPERATORE = O.CODICE ');
qt.Add(' join LG_CAUSA C on T.CAUSALE = C.CODICE ');
qt.Add('where T.DATA >= :data1 and T.DATA <= :data2 ');
if CheckBox3.Checked then
qt.Add(' and T.INCASSO = :pagamento ');
if CheckBox5.Checked then
qt.Add(' and T.TERMINALE = :terminale ');
qt.Add('order by G.NUM_PROG');
FDquery3.ParamByName('data1').AsDate := Datetimepicker1.Date;
FDquery3.ParamByName('data2').AsDate := Datetimepicker2.Date;
if CheckBox3.Checked then
FDQuery3.ParamByName('pagamento').AsString := Combobox3.Items [Combobox3.Itemindex];
if CheckBox3.Checked then
FDQuery3.ParamByName('terminale').AsString := Combobox5.Items [Combobox5.Itemindex];
FDQuery3.Open;
在此选项中,您不会引入额外的切换参数,而是仅在用户检查使用它们时添加值参数。如果用户取消选中它们 - 那么您不会将它们包含在您的 SQL 文本中,因此您不会为它们分配任何值(无论如何它们都不会被发现)。
5) 您可以使用 BETWEEN - 它可能更容易阅读。
...
where ( T.DATA BETWEEN :data1 AND :data2 )
and T.INCASSO = :pagamento
....