jOOQ 3.9:"ORA-00918: column ambiguously defined" 在具有匹配列名的连接表上
jOOQ 3.9: "ORA-00918: column ambiguously defined" on joined tables with matching column names
在最新的 3.9 更新之后,jOOQ 现在似乎正在使用新的 Oracle 12c row_limiting_clause 进行行限制,而不是旧的 'rownum' 语法。这会导致 Oracle 12c 中的 "ORA-00918: column ambiguously defined" 连接 table 具有匹配的列名。
select
student.name,
school.name
from student
join school on student.schoolId = school.id
offset 0 rows fetch next 25 rows only;
然而,根据 Oracle 的文档 [1],新的子句
If the select list contains columns with identical names and you specify the row_limiting_clause, then an ORA-00918 error occurs. This error occurs whether the identically named columns are in the same table or in different tables.
当您在使用 row_limiting_clause.
时尝试 select 来自两个连接的 table 的所有列时,这会导致问题
如果每个列都单独使用别名,那么 Record.into() 可能无法自动将返回的记录转换为两个 table 记录。
有没有什么好的自动方法可以通过 jOOQ 将别名列映射到 table 记录?
[1] https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#SQLRF01702
两列具有相同的标识符 name
,这是不允许的。
您可以像这样使用别名:
select
student.name student_name,
school.name school_name
from student
join school on student.schoolId = school.id
offset 0 rows fetch next 25 rows only;
这是 jOOQ 3.9 (#5451) 中的已知问题/回归,已在 jOOQ 3.9.1 中修复。作为解决方法,您可以使用 SQLDialect.ORACLE11G
恢复为 limit()
和 offset()
.
的 "old" ROWNUM
过滤仿真
仅供参考,这是我将别名列映射到类型化记录的解决方案:
// following the student, school scenario from the first post
// define the prefixes
final String st_prefix = "st_";
final String sc_prefix = "sc_";
// define the tables to map to at the end
// the table names themselves aren't getting aliased in this example, but the fields are
final Table<StudentsRecord> st = STUDENTS.as(STUDENTS.getName(), field -> st_prefix + field.getName());
final Table<SchoolsRecord> sc = SCHOOL.as(SCHOOLS.getName(), field -> sc_prefix + field.getName());
// define the aliased columns
final Field<?>[] stFields = Arrays.stream(STUDENTS.fields()).map(field -> field.as(st_prefix + field.getName())).toArray(Field[]::new);
final Field<?>[] scFields = Arrays.stream(SCHOOLS.field()).map(field -> field.as(sc_prefix + field.getName())).toArray(Field[]::new);
query = context.select(stFields, scFields)
.from(STUDENTS)
.join(SCHOOLS).on(STUDENTS.SCHOOL_ID.equal(SCHOOLS.SCHOOL_ID)
.offset(0)
.limit(25);
// map the aliased columns into the tables expecting aliased columns
return query.fetchInto(record -> new Tuple2<>(record.into(st), record.into(sc)));
此解决方案依赖于 jOOQ 3.9 功能,'functional aliases' 1. 这用于创建别名列可以使用 Record.into() 方法映射到的表。
这是我能想到的最短的解决方案——使用 12c 特性。
在最新的 3.9 更新之后,jOOQ 现在似乎正在使用新的 Oracle 12c row_limiting_clause 进行行限制,而不是旧的 'rownum' 语法。这会导致 Oracle 12c 中的 "ORA-00918: column ambiguously defined" 连接 table 具有匹配的列名。
select
student.name,
school.name
from student
join school on student.schoolId = school.id
offset 0 rows fetch next 25 rows only;
然而,根据 Oracle 的文档 [1],新的子句
If the select list contains columns with identical names and you specify the row_limiting_clause, then an ORA-00918 error occurs. This error occurs whether the identically named columns are in the same table or in different tables.
当您在使用 row_limiting_clause.
时尝试 select 来自两个连接的 table 的所有列时,这会导致问题如果每个列都单独使用别名,那么 Record.into() 可能无法自动将返回的记录转换为两个 table 记录。
有没有什么好的自动方法可以通过 jOOQ 将别名列映射到 table 记录?
[1] https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#SQLRF01702
两列具有相同的标识符 name
,这是不允许的。
您可以像这样使用别名:
select
student.name student_name,
school.name school_name
from student
join school on student.schoolId = school.id
offset 0 rows fetch next 25 rows only;
这是 jOOQ 3.9 (#5451) 中的已知问题/回归,已在 jOOQ 3.9.1 中修复。作为解决方法,您可以使用 SQLDialect.ORACLE11G
恢复为 limit()
和 offset()
.
ROWNUM
过滤仿真
仅供参考,这是我将别名列映射到类型化记录的解决方案:
// following the student, school scenario from the first post
// define the prefixes
final String st_prefix = "st_";
final String sc_prefix = "sc_";
// define the tables to map to at the end
// the table names themselves aren't getting aliased in this example, but the fields are
final Table<StudentsRecord> st = STUDENTS.as(STUDENTS.getName(), field -> st_prefix + field.getName());
final Table<SchoolsRecord> sc = SCHOOL.as(SCHOOLS.getName(), field -> sc_prefix + field.getName());
// define the aliased columns
final Field<?>[] stFields = Arrays.stream(STUDENTS.fields()).map(field -> field.as(st_prefix + field.getName())).toArray(Field[]::new);
final Field<?>[] scFields = Arrays.stream(SCHOOLS.field()).map(field -> field.as(sc_prefix + field.getName())).toArray(Field[]::new);
query = context.select(stFields, scFields)
.from(STUDENTS)
.join(SCHOOLS).on(STUDENTS.SCHOOL_ID.equal(SCHOOLS.SCHOOL_ID)
.offset(0)
.limit(25);
// map the aliased columns into the tables expecting aliased columns
return query.fetchInto(record -> new Tuple2<>(record.into(st), record.into(sc)));
此解决方案依赖于 jOOQ 3.9 功能,'functional aliases' 1. 这用于创建别名列可以使用 Record.into() 方法映射到的表。
这是我能想到的最短的解决方案——使用 12c 特性。