Java SQLite无法通过JDBC和jOOQ在SELECT中找到现有列
我在使用SQLite和JDBC时遇到了一些奇怪的结果(实际上是通过JOOQ,但是这个问题可以通过JDBC手动执行查询字符串来重现)。我的数据库由三个表组成,包括多对多和一对多关系。我尝试选择“main”表的所有值,并从关系表中连接所有需要的值:Java SQLite无法通过JDBC和jOOQ在SELECT中找到现有列,java,sql,sqlite,jdbc,jooq,Java,Sql,Sqlite,Jdbc,Jooq,我在使用SQLite和JDBC时遇到了一些奇怪的结果(实际上是通过JOOQ,但是这个问题可以通过JDBC手动执行查询字符串来重现)。我的数据库由三个表组成,包括多对多和一对多关系。我尝试选择“main”表的所有值,并从关系表中连接所有需要的值: 选择location.name, 世界,世界, 玩家,玩家 从地点 加入世界 在位置上。“世界id”=世界。“世界id” 左侧外部连接(位置2层 加入玩家 在location2player上。“玩家id”=玩家。“玩家id”) 在位置上。“位置id”=位
选择location.name,
世界,世界,
玩家,玩家
从地点
加入世界
在位置上。“世界id”=世界。“世界id”
左侧外部连接(位置2层
加入玩家
在location2player上。“玩家id”=玩家。“玩家id”)
在位置上。“位置id”=位置2层。“位置id”
在JDBC中,此查询失败:
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such column: player.player)
当我在外部SQLite编辑器(如用于Firefox的SQLite管理器)中执行查询时,它会按预期工作
我使用的sqlite-jdbc-3.7.2
无法更改。作为参考,JOOQ查询是:
为什么JDBC中的查询会失败?我应该如何修复它?虽然我认为您编写了有效的ANSI SQL,但很可能是SQLite对您的语句的解释略有不同。但你真的不需要这样做。试试这个:
选择location.name,
世界,世界,
玩家,玩家
从地点
加入世界
在位置上。“世界id”=世界。“世界id”
左外连接位置2player
在位置上。“位置id”=位置2层。“位置id”
左外接球员
在location2player上。“玩家id”=玩家。“玩家id”
我能够在sqlite-jdbc-3.7.2下使用
sql=
“选择location.name,”+
“世界,世界,”+
“player.player”+
“来自”+
“位置”+
“加入世界”+
“在位置上。\“世界id\”=世界。\“世界id\”+
“左外连接(位置2player”+
“加入”+
“玩家”+
“在位置2层上。\“玩家id\”=玩家。\“玩家id\”)+
“在位置上。\“位置id\”=位置2层。\“位置id\”;
问题似乎是location2player
和player
表被“隐藏”在子联接的括号()
内,并且对初始列列表和最终ON子句不可用。以下语句通过为子查询提供别名并在这两个位置使用别名来避免该问题:
sql=
“选择”+
location.name+
“世界,世界,”+
“playerlocation.player”+
“来自”+
“位置”+
“加入”+
“世界”+
“在位置上。\“世界id\”=世界。\“世界id\”+
“左外联接”+
"( " +
选择location2player.“位置id”,player.player+
“来自”+
“位置2层”+
“加入”+
“玩家”+
“在location2player上。\“玩家id\”=玩家。\“玩家id”+
)作为playerlocation“+
“在位置上。\“位置id\”=播放器位置。\“位置id\”;
JDBC驱动程序使用的SQLite版本是什么?这很有效,谢谢。现在的问题可能是,我如何正确地将其移植到JOOQ的逻辑中——也许@lukaseder有一个想法?使用三个分开的.as(“playerlocation”)
子句似乎有点难看。@e:那么这真的是SQLite的限制吗?我本以为原始语句是有效的ANSI-SQL。我想,只要将您的查询重写为@LukasEder就行了,因为它的价值是,原始SQL查询是“Transitional SQL-92”。谢谢您的反馈。是的,我想是的。在括号中嵌套联接的情况很少,但它应该像未嵌套联接一样工作。定义表的范围不应像涉及派生表时那样改变(如在您的解决方案中)。
create.select(LOCATION.NAME,WORLD.WORLD_,PLAYER.PLAYER_)
.from(LOCATION
.join(WORLD)
.on(LOCATION.WORLD_ID.eq(WORLD.WORLD_ID)
)
.leftOuterJoin(LOCATION2PLAYER
.join(PLAYER)
.onKey()
)
.on(LOCATION.LOCATION_ID.eq(LOCATION2PLAYER.LOCATION_ID)
)
.fetch()