【问题标题】:dbExpress design questiondbExpress 设计问题
【发布时间】:2011-08-18 05:09:07
【问题描述】:

有没有人知道(或想知道)为什么 TSqlDataset 有一个 commandtext 属性(字符串)而 TSqlQuery 有一个 sql 属性(tstrings)?

考虑sql语句

select id, name from
table
order by name

如果我使用 TSqlQuery,那么我可以通过访问 sql[1] 动态更改查询中的表名,但如果我使用的是 TSqlDataset(如果我需要双向数据集,我必须这样做,数据集是连接的到提供者,然后到 tclientdataset),我必须逐字设置命令文本字符串。虽然上面的例子是微不足道的,但当 sql 语句涉及更多时,它可能是一个问题。

更新: 从到目前为止的cmets和答案来看,我似乎被误解了。我不太关心提高组件的运行时性能(当查询需要一秒钟时,一毫秒有什么关系),但我确实关心程序员(即我)和维护程序的能力。在现实生活中,我有以下存储在 TSqlQuery 中的查询:

select dockets.id, dockets.opendate, customers.name, statuses.statname,
dockets.totalcost, dockets.whopays, dockets.expected, dockets.urgent,
(dockets.totalcost - dockets.billed) as openbill,
(dockets.totalcost - dockets.paid) as opencost,
location.name as locname, dockets.attention,
statuses.colour, statuses.disporder, statuses.future, dockets.urgcomment
from location, statuses, dockets left join customers
on dockets.customer = customers.id
where dockets.location = location.id
and dockets.status = statuses.id

我没有计算字符串中的字符数,但我确定超过 255 个,因此排除了将查询存储在简单字符串中。在某些情况下,我想通过添加行“and statuses.id = 3”或“and customers.id = 249”来过滤显示的数据量。如果查询存储为 TStrings,那么我可以在基本查询中添加虚拟行“and 1 = 1”,然后根据需要更新该行。但是查询是一个长字符串,我无法轻松访问它的结尾。

我目前正在做的(代替更好的解决方案)是创建另一个 TSqlDataSet,并将其命令文本设置为默认的 TSqlDataSet 的命令文本,同时附加额外的条件。

【问题讨论】:

  • 如果考虑到更改 SQL 文本语句所花费的时间与语句本身的执行时间有关,则无需考虑更改整个 SQL 字符串。在所有情况下,整个 SQL 语句都将被发送到后台 DB 驱动程序,因此这两种方法是相等的。 (即使设置 SQL[1] 可能会慢一点,如果 ParamCheck=true - 请参阅 da-soft 答案)如果您想要更快的东西,请不要使用 dbExpress,而是使用直接数据库访问组件。
  • 1) 抱歉,那不是 1 毫秒。只要相信... 2) 255 不是 Delphi 字符串的限制,因为 Delphi2。 3) 你可以有效地使用 as TStrings, as String。我的答案有一切。
  • 以防大软没说清楚;字符串的 255 个字符限制适用于 1995 年的 Delphi 1。自 1996 年的 2.0 版以来,它不再适用于 Delphi,那是 15 年前的事了!多行字符串可以在 delphi 属性检查器中编辑,如果它们注册了设计时“帮助器”,在这种情况下,对于 TSqlDataSet.CommandText,它已经可供您使用。只需单击属性检查器中的省略号按钮,您就会得到一个漂亮的 SQL 编辑器帮助对话框。它不是 RapidSQL 或 Toad,但比使用 1" 宽的字符串属性要好。

标签: delphi dbexpress


【解决方案1】:

1) TSQLQuery 是为了与 BDE TQuery 兼容。 BDE TQuery 具有SQL: TStrings 属性。 TSQLDataSet 应该用于新应用程序。

2) 虽然SQL: TStrings 对某些任务很有用,但它也容易出错。程序员经常忘记在再次填充之前清除 SQL 属性。此外,如果您的查询很大,SQL 的填充可能会导致性能下降。因为在每个SQL.Add(...) 调用 dbExpress 代码都会在 ParamCheck 为 True 时解析查询。这可以通过使用BeginUpdate / EndUpdate 或将 ParamCheck 设置为 False 来解决。但请注意,将 ParamCheck 设置为 False 会停止自动创建参数。

SQLQuery1.SQL.BeginUpdate;
try
  SQLQuery1.SQL.Clear;
  SQLQuery1.SQL.Add('SELECT * FROM');
  SQLQuery1.SQL.Add('Orders');
finally
  SQLQuery1.SQL.EndUpdate;
end;

CommandText 没有此类问题。

3) 您可以使用Format 函数来构建动态SQL 字符串:

var
  sTableName: String;
...
sTableName := 'Orders';
SQLDataSet1.CommandText := Format('select * from %s', [sTableName]);

4) 其他数据访问库,如AnyDAC,有macro variables,简化了动态查询文本构建。例如:

ADQuery1.SQL.Text := 'SELECT * FROM &TabName';
ADQuery1.Macros[0].AsRaw := 'Orders';
ADQuery1.Open;

【讨论】:

  • “SQL 的填充可能导致性能下降”很有趣……没错:每当执行 SQL.Add 时都会调用 TSQLQuery.QueryChange 方法。所以最好设置ParamCheck=false
【解决方案2】:

我不得不说 TSqlQuery 使用 TStrings(Delphi 2010 中的 TWideStrings),因为它更加灵活。

假设您的查询是:

Select
Item1,
Item2,
Item3,
Item4
FROM MyTable

  • 它更容易阅读
  • 您可以复制并粘贴到外部查询工具中,它保持格式不变
  • 注释部分很容易

Select
Item1,
/*
Item2,
Item3,
*/
Item4
FROM MyTable

  • 您可以轻松添加项目

Select
Item1,
Item2,
Item2a,
Item2b,
Item3,
Item3a,
Item3b,
Item4
FROM MyTable

尝试对一组连续的字符执行此操作,这些字符永远在一个长行中,并且在编辑窗口内没有换行符,该编辑窗口总是很小,无法查看,不允许包装文本等等等。

只需 0.02 美元。

【讨论】:

  • 我非常同意。不过,我在问,似乎选择了一个字符串而不是字符串列表的设计问题可能是什么。
  • 错了。只需单击省略号按钮[...] 即可在多行编辑字段中编辑属性。仅仅因为 TStrings 只是在顶层视图中显示 (Strings) 并没有理由认为 TStrings 更好。
  • 在设计时编辑字符串时,我确实单击了省略号按钮。我问的是查询的运行时操作,当查询存储为字符串而不是字符串列表时,这更难做到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 2011-11-09
  • 2011-01-16
  • 2011-03-21
相关资源
最近更新 更多