【问题标题】:Delphi Firedac - FieldName issueDelphi Firedac - 字段名称问题
【发布时间】:2021-09-30 11:14:04
【问题描述】:

我将带有 MS Access 基础的应用程序 (Delphi 10.3) 从 ADODB 迁移到 Firedac。 当某些 TField FieldName 名称复杂时,我遇到了问题: 简单示例:CREATE TABLE TEST ([SE_NAME] CHAR(3))

SELECT * FROM TEST T1 LEFT JOIN TEST T2 ON T1.SE_NAME=T2.SE_NAME这样的查询

我希望 FieldNames :'T1.SE_NAME' 和 'T2.SE_NAME'(如 Access 2013 中)。

使用 ADODB TADOQuery :

  var f: TField;
  var s: string := '';
  for f in Query.Fields do
    s := s +  f.FieldName + ' ;' ;

s'T1.SE_NAME ;T2.SE_NAME ;' 好的。

使用 Firedac TFDQuery:

  var f: TField;
  var s: string := '';
  for f in Query.Fields do
    s := s +  f.FieldName + ' ;' ;

s'SE_NAME ;SE_NAME_1 ;':不正常:FireDac 更改了列名。

如何在不更改 SQL 查询的情况下(使用 Firedac 选项?)保留真实的列名(为了兼容需要)?

在 MSAccess (2013) 中,SELECT * FROM TEST T1 LEFT JOIN TEST T2 ON T1.SE_NAME=T2.SE_NAME 的结果是:

请注意:

  • 我知道如何使用查询、别名...但我需要保留查询以保持兼容性。
  • 查询只是示例(不是真正的查询)。

【问题讨论】:

  • 在这种情况下,我使用别名:SELECT T1.SE_NAME SE_NAME1, T2.SE_NAME SE_NAME2 FROM TEST T1 LEFT JOIN TEST T2 ON ...
  • full syntax of aliases 是:SELECT whatever AS alias, other AS newname... FROM table AS abbreviation, ...,就像您已经使用 FROM test (AS) T1 的缩写形式一样。
  • 我不是 SQL 期望,但我知道 JOIN 是什么,但如果您只从 T1 中选择数据,为什么您希望 T2 中的任何字段出现在结果集中,因此在Fields 列表中?
  • @RemyLebeau A SELECT * 将从查询的FROM 部分涉及的所有表中获取所有字段。
  • 您是否有很多查询要更改,您已经准备好因此花费 500 点而不是仅仅修复它们?不幸的是,您所要求的可能是不可能的。但是您可以直接查看 FireDAC 源代码来确定。

标签: delphi firedac


【解决方案1】:

这被称为technical dept:您过去做出了您认为很好的决定,但现在事实证明,与过去您选择不同(并且成本更低)相比,它造成的损害更大。

SELECT * FROM test JOIN test 立即提出问题:

  • 为什么同一个表会连接到自身?这很少有道理。
  • 真的需要所有列吗?这效率很低。

你应该克服你的设计决定并修复它:

  • 仅选择您实际需要的那些列。无论表格有多少列。这也有助于在追踪问题时避免歧义(同时有助于提高整体性能)。

  • 使用别名准确地得到你想要的结果:

    • 如果您希望 t1.column 作为结果中的列名,则通过 SELECT t1.column AS "t1.column" 定义它(Ansi SQL,大多数 DBMS 都支持这一点)。
    • MS Access 需要方括号和does not allow dots in aliases(错误信息是“标点符号”但即逗号和冒号都可以),所以你必须想出自己的逻辑,即下划线:SELECT t1.column AS [t1_column] .或者直接使用独特的别名。

    如果你不定义它,你不能指望没有惊喜(FireDAC 肯定想帮助你处理带下划线的后缀,否则它只会覆盖现有的匹配项)。只需在不同的 DBMS 中尝试 SELECT 1+ 1* 2 FROM table 并查看生成的结果列名称 - 我想知道您如何准备在不使用列别名的情况下访问它。

  • 您甚至可以多次从同一个表中选择同一列:SELECT column AS c1, column+ 2021 AS c2 FROM test,但您希望不使用别名就能神奇地解决问题?只需使用它们 - 不要让它未定义。 SELECT name AS name FROM test AS t 有疑问(即使这样,也不能完全确定生成的列名是 name 还是 NAME - 这就是为什么你应该在别名周围使用引号)。

  • 如果您想将SELECT * FROMQuery.Fields.Fieldname 混合以获取一个表可能拥有的列名列表,那么每个表 都可以这样做,而不是将多个表放入查询中。甚至这种方法也不好 - 而是查阅 DBMS 信息架构 - in FireDAC there are Get*Names() methods for that

交叉链接FireDAC adding underscoreSQL select join: is it possible to prefix all columns as 'prefix.*'?

【讨论】:

  • 感谢详细的帖子,但请注意,我只想回答我的问题,而不是解释错误或良好的软件设计。当您对“SELECT * FROM test JOIN test”有疑问时,一些答案: 1/ 为什么同一张表是针对自身连接的:它是一个分层组织,其中项目是其他项目的父母(和/或)孩子。 2/ 真的需要所有列吗? : 一定不 !这只是一个需要简洁的例子。
  • @philnext 如果您更愿意“只是”得到答案,而无需进一步解释为什么这是一个死胡同以及尝试和分析了多少,我可以编辑我的所有文本以将其简化为“ 不可能”,但我无法想象这会让你更快乐。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 2016-05-04
  • 1970-01-01
相关资源
最近更新 更多