我有一个带有表Cdr的数据库(postgresql)。每个月都会在数据库中创建一个与表Cdr具有相同模式的新表,名为Cdr__(例如Cdr_2016_04)。
我正在尝试使用Jooq根据提供的日期查询数据库。麻烦的是:
context.select(CDR.fields())
.from("cdr_2017_01")
.where(CDR.FIELD1.eq("somevalue")
.and(CDR.FIELD2.notEqual("value 2")
.and(CDR.FIELD2.notEqual("value 3")))
.fetchInto(Cdr.class);
不起作用,因为它表示
org.jooq.exception.DataAccessException:...来自cdr_2017_01其中(“public”。“cdr”。“field1”=?和“public”。“cdr”。“field2”<>?和“ public“。”cdr“。”field2“<>?)];错误:缺少表“cdr”
的FROM子句条目
我尝试使用别名使其'cdr_2017_01 as cdr',但由于cdr已经存在而失败。似乎因为我使用CDR.FIELD1和CDR.fields(),jooq要求from子句中的表是CDR。有没有办法使这个通用,或者我不应该使用Jooq进行这种查询?
答案 0 :(得分:1)
您获得的错误源自您在字段引用中使用生成的CDR
字面值,例如: CDR.FIELD1
。所有这些字段都将使用"cdr"
表完全限定,而不是您在from子句中放入的"cdr_2017_01"
表。
您可以打开debug logging以查看jOOQ生成并发送到服务器的格式化SQL字符串。
最简单的解决方法是将"cdr_2017_01"
表格替换为"cdr"
,如下所示:
context.select(CDR.fields())
.from("cdr_2017_01 as cdr")
.where(CDR.FIELD1.eq("somevalue")
.and(CDR.FIELD2.notEqual("value 2")
.and(CDR.FIELD2.notEqual("value 3")))
.fetchInto(Cdr.class);
这在一定程度上适用于大多数查询。
您应该使用runtime schema / table mapping feature。它专为这些多租户/分区用例而设计。
然后你可以写下以下内容:
DSL.using(connection, new Settings()
.withRenderMapping(new RenderMapping()
.withSchemata(new MappedSchema()
.withInput("my_schema_name")
.withTables(new MappedTable()
.withInput(CDR.getName())
.withOutput(CDR.getName() + "_2017_01")))))
.select(CDR.fields())
.from(CDR)
.where(CDR.FIELD1.eq("somevalue")
.and(CDR.FIELD2.notEqual("value 2")
.and(CDR.FIELD2.notEqual("value 3")))
.fetchInto(Cdr.class);
当然,另一个选择可能是使用PostgreSQL的分区功能,如果您可能不需要在客户端中明确指定表名:
https://www.postgresql.org/docs/current/static/ddl-partitioning.html