【问题标题】:Missing table alias falls back to using only field name缺少表别名回退到仅使用字段名称
【发布时间】:2017-09-12 13:54:41
【问题描述】:

我的桌子

N
ID|T_ID
1|1
2|2

T
ID|NAME
1|T1
2|T2

如下使用表格

com.db.N N_TABLE = N.as("N_TABLE");
com.db.T T_TABLE = T.as("T_TABLE");
com.db.T T2_TABLE = T.as("T2_TABLE"); //Random alias, not used in query

SelectQuery selectQuery = create.selectQuery();
selectQuery.addFrom(N_TABLE);
selectQuery.addJoin(T_TABLE, JoinType.LEFT_OUTER_JOIN, T_TABLE.ID.eq(N_TABLE.T_ID));

Result<Record> result = selectQuery.fetch();
for (Record record : result) {
  System.out.println(record.get(T2_TABLE.NAME));
}

它给出了一个模棱两可的警告,但即使别名是错误的,它仍然会得到值。我希望它返回“null”,我猜它回退到只使用字段名称。

知道在别名错误的情况下我应该如何使用它来获取“null”吗?

编辑

我会尝试提供一个更具体的例子

我的表如下

CREATE TABLE user
(
  id bigserial NOT NULL,
  username character varying(200) NOT NULL,
  last_name character varying(100),
  created_user_id bigint NOT NULL,
  modified_user_id bigint NOT NULL,
  CONSTRAINT pk_user PRIMARY KEY (id),
  CONSTRAINT user_username_key UNIQUE (username)
)

表格中的数据

3;"admin";"admin";3;3
4;"test";"test";4;3

代码

//Input params
Long userId = 4L;
boolean includeModifiedUser = false;

User userTable = USER.as("userTable");
User modifiedUserTable = USER.as("modifiedUserTable");

SelectQuery selectQuery = create.selectQuery();
selectQuery.addFrom(userTable);

//In some cases I want to include the last modifier in the query
if (includeModifiedUser) {
    selectQuery.addJoin(modifiedUserTable, JoinType.LEFT_OUTER_JOIN, modifiedUserTable.ID.eq(userTable.MODIFIED_USER_ID));
}

selectQuery.addConditions(userTable.ID.eq(userId));
Record record = selectQuery.fetchOne();

System.out.println(record.get(userTable.LAST_NAME)); //prints "test1"
System.out.println(record.get(modifiedUserTable.LAST_NAME)); //prints "test1", would expect null as modifiedUserTable is currently not joined

在 jooq 3.9.3 和 3.9.5 上测试

【问题讨论】:

  • 确切的警告是什么?还有,这两个表的描述真的完整吗?
  • 当我第一次写这个问题时,我也得到了org.jooq.impl.Fields: Ambiguous match found for ...,但现在无法重现。问题本身仍然存在。
  • 我的猜测是当它无法解析表格时,它会退回到仅进行字段比较并导致检索错误数据。

标签: java sql jooq


【解决方案1】:

按设计工作

在 SQL 中,结果集中没有限定列名这样的东西。相反,结果集(与任何其他表一样)具有一组列,每列都有一个名称,由 jOOQ 的Field.getName() 描述。现在,“不幸的是”,在顶级 SELECT 语句中,在所有 SQL 方言以及 jOOQ 中,您都可以有重复的列名。当您连接两个表并且两个表都具有例如ID 列。这样,您不必因为出现歧义而重命名每一列。

如果表/结果中确实有重复的列名,jOOQ 将应用TableLike.field(Field) 中描述的算法

这将返回:

  • 与参数字段相同的字段(通过身份比较)。
  • 等于参数字段的字段(完全匹配的完全限定名称)。
  • 等于参数字段的字段(部分匹配限定名)。
  • 名称与参数字段名称相同的字段。
  • 否则为空。

如果多个字段具有相同的名称,则返回第一个并记录警告。

如您所见,这里的基本原理是,如果结果集中的字段与您在结果集中查找的字段之间没有完全或部分标识或限定名称相等,则字段名称为inField.getName() 用于查找字段。

关于列匹配歧义的旁注

一开始,您提到日志中有一个“模糊匹配”警告,然后就消失了。该警告表明两列通过相同的Field.getName(),但它们都不是如前所述的“精确”匹配。在这种情况下,您将获得第一列作为匹配项(出于历史原因)以及该警告,因为这可能不是您想要做的。

【讨论】:

    猜你喜欢
    • 2022-11-24
    • 2015-04-14
    • 1970-01-01
    • 2020-08-12
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    相关资源
    最近更新 更多