【问题标题】:Retrieving metadata of the result of a TQuery检索 TQuery 结果的元数据
【发布时间】:2011-03-14 09:07:12
【问题描述】:

在我们的应用程序中,用户可以输入 SQL 代码来从 NexusDB 数据库中检索数据。 我们希望在不实际执行查询的情况下确定此类查询结果的元数据。我们使用元数据来确定字段的数量和每个结果字段的数据类型。

[加法] 我们将此功能用作用户定义的转换过程的一部分。实际的转换稍后在类似批处理的过程中完成,但我们需要事先元数据,因此用户可以在转换中指定其他字段特征或修改,如应用插件、创建父子关系等。 [/加法]

到目前为止,我们基本上通过在 SQL 查询中添加 WHERE FALSE 或将所有已经存在的 WHERE 语句替换为 WHERE FALSE AND 来做到这一点。但是当然我们必须解析整个 SQL 以确定要调整的正确 where 子句的确切位置,同时考虑到 cmets、嵌套 SELECTS、JOIN 和其他子句。这种方式变得相当复杂:-(

这样做的另一个缺点是,即使我们事先知道结果集将为空,但大多数时候查询的执行仍然需要很长时间。

我们想知道是否有其他方法可以实现这一目标。

即TQuery 对象必须有自己的解析器,将 SQL 语句拆分为不同的子句。如果我们可以在执行之前更改 where 子句,我们就不必自己进行解析。但是我们有点急于深入 TQuery 对象的内部,只是为了发现没有办法以我们想要的方式使用它。

有人对此有什么建议吗?

【问题讨论】:

  • 您正在尝试做一些非常不典型的事情:获取返回字段的列表而不获取实际字段。唯一可能有帮助的是Prepare 方法,但在我的测试中它没有设置Fields。您使用 BDE 并在访问数据库之前至少经过两次间接访问这一事实无济于事。我会尝试简单地解决该问题,但不尝试事先获取字段列表。解析 SQL 可能是一项艰巨的任务,尤其是在面对涉及联合和联接的复杂查询时;
  • 关于深入研究TQuery:别打扰,答案不存在。只有数据库知道答案,TQuery 只是一个中介。想想这个查询:SELECT * FROM MYTABLE。很明显,TQuery 无法知道MYTABLE 中的内容,只有数据库知道!
  • @Cosmin 查看原始问题中的补充内容,顺便说一下,我们没有使用 BDE。

标签: sql delphi delphi-2007 nexusdb


【解决方案1】:

您已经做的一个变体是将原始 SQL 语句放在嵌套选择中,而不是修改 where 子句。 如果select * from MyTable 是您的复杂查询,您可以像这样嵌入它以获得任何结果。

select *
from
(
  select *
  from MyTable
) as xx
where 0=1

我只在 SQL Server 中测试过这个,而不是在 NexusDB 中

【讨论】:

  • 我刚刚用 Firebird 2.5 尝试了这个查询。它可以工作(如:它返回 0 条记录),但查看查询计划分析器,它确实从“MyTable”中读取了所有内容——本质上是处理整个查询。 SQL Server 是否有类似的功能?您确定它没有运行完整的查询,然后根本没有返回任何内容吗?
  • @Cosmin SQL Server 不运行完整查询。我已经通过查询计时和查询计划进行了测试。
  • 这会起作用,但如果我们正在处理嵌套的 select 语句或选择的联合,它只会忽略最后一刻的数据(至少在 NexusDB 中)。我们现在将所有出现的 where 替换为 where false ,这将永远不会产生任何数据(只有时间得出这个结论)
【解决方案2】:

深入了解客户端 TnxQuery 组件无济于事。它只是一个语句和游标句柄的包装器。在客户端检索您所追求的元数据的唯一方法是从游标句柄。只有在执行查询时才会生成游标句柄。

目前,在执行查询时最小化正在执行的工作的唯一方法是您已经在做的事情。

如果您在我们的问题跟踪器 (http://www.nexusdb.com/mantis/view_all_bug_page.php) 中提交功能请求,我们可以研究指定一些标志来告诉引擎“从不处理任何数据”而不需要弄乱查询本身的可能性。

【讨论】:

  • @Thorsten Engler:我从您的回复中得知您来自 NexusDB。我们之前已经发布了添加此类内容的请求,而您(nexsudb)的回答是:“使用 WHERE FALSE”。如果这样的请求有更多机会被实际研究,我很乐意再次发布它
  • 是的,我是。你把它发布到他的问题跟踪器了吗?问题是什么?
  • @Thorsten Engler:我的同事 Hans Hasenack 于 5 年前(2006 年 9 月 12 日)在新闻组 nexusdb.public.support.sql 中发布了它,主题为“返回一个空数据集”,回到过去NexusDB V1 或 V2。他在“SELECT NONE”行中提出了一些建议
  • 谢谢,现在它在问题跟踪器中,它不会再丢失了。
  • 标记为已接受答案...假设功能请求将产生有用的结果
【解决方案3】:

您还可以尝试将带有 TDatasetProvider 的 TClientDataset 链接到原始 TQuery(或任何 TDataset 后代)。然后将 TClientDataset 的 PacketRecords 属性设置为 0,并打开它。它将检索 TClientDataSet 中的字段,没有任何数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 2014-06-17
    • 2019-11-28
    • 2016-04-30
    相关资源
    最近更新 更多