问题简介: 尝试使用SQLite数据库在Java中执行SQL查询时,SQL语句无法从execute()或executeQuery()方法返回。换句话说,系统在执行此SQL语句时“挂起”。
问题: 我怎么做错了解释为什么ResultSet永远不会“返回?”
疑难解答 我试图缩小问题,问题似乎与Java execute()或executeQuery()有关。 ResultSet似乎永远不会返回。例如,我尝试直接在SQLite中执行完全相同的查询(即使用SQLite数据库管理器)。查询(Java外部)在大约5ms内执行并返回有效的结果集。
注意:不会抛出任何异常。该系统似乎只是“挂起”并且在手动终止之前变得没有响应。 (等待超过10分钟。)
代码: 我对此代码进行了大量编辑,以使问题更易于查看。 (在生产中,它使用Prepared Statements。但是,两种方法都会出现错误 - 直接Statement和准备好的Statement版本。)
基本上,SELECT返回单个数据库项,以便用户可以查看该项。
Statement st = conn.createStatement() ;
ResultSet rs = st.executeQuery("SELECT DISTINCT d1.id, d1.sourcefullfilepath, " +
"d1.sourcefilepath, d1.sourcefilename, d1.classificationid, d1.classid, " +
"d1.userid FROM MatterDataset, (SELECT MatterDataset.id, " +
"MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath, " +
"MatterDataset.sourcefilename, MatterDataset.matterid , " +
"DocumentClassification.classificationid, DocumentClassification.classid," +
" DocumentClassification.userid FROM MatterDataset " +
"LEFT JOIN DocumentClassification ON " +
"DocumentClassification.documentid = Matterdataset.id " +
"WHERE ( DocumentClassification.classid = 1 OR " +
"DocumentClassification.classid = 2 ) AND " +
"DocumentClassification.userid < 0 AND " +
"MatterDataset.matterid = \'100\' ) AS d1 " +
"LEFT JOIN PrivilegeLog ON " +
"d1.id = PrivilegeLog.documentparentid AND " +
"d1.matterid = PrivilegeLog.matterid " +
"WHERE PrivilegeLog.privilegelogitemid IS NULL " +
"AND MatterDataset.matterid = \'100\' " +
"ORDER BY d1.id LIMIT 1 ;") ;
配置: Java 6, JDBC Driver = Xerial sqlite-jdbc-3.7.2, SQLite 3, 视窗
更新 次要修订:当我继续使用它时,在SQL语句的开头添加MIN(d1.id)至少返回一个ResultSet(而不是“挂起”)。但是,这并不是我想要的,因为MIN省略了LIMIT功能。
Statement st = conn.createStatement() ;
ResultSet rs = st.executeQuery("SELECT DISTINCT MIN(d1.id), d1.id,
d1.sourcefullfilepath, " +
"d1.sourcefilepath, d1.sourcefilename, d1.classificationid, d1.classid, " +
"d1.userid FROM MatterDataset, (SELECT MatterDataset.id, " +
"MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath, " +
"MatterDataset.sourcefilename, MatterDataset.matterid , " +
"DocumentClassification.classificationid, DocumentClassification.classid," +
" DocumentClassification.userid FROM MatterDataset " +
"LEFT JOIN DocumentClassification ON " +
"DocumentClassification.documentid = Matterdataset.id " +
"WHERE ( DocumentClassification.classid = 1 OR " +
"DocumentClassification.classid = 2 ) AND " +
"DocumentClassification.userid < 0 AND " +
"MatterDataset.matterid = \'100\' ) AS d1 " +
"LEFT JOIN PrivilegeLog ON " +
"d1.id = PrivilegeLog.documentparentid AND " +
"d1.matterid = PrivilegeLog.matterid " +
"WHERE PrivilegeLog.privilegelogitemid IS NULL " +
"AND MatterDataset.matterid = \'100\' " +
"ORDER BY d1.id LIMIT 1 ;") ;
答案 0 :(得分:1)
多么糟糕的SQL语句(对不起)!我不知道SQLite,但为什么不简化为:
SELECT DISTINCT md.id, md.sourcefullfilepath, md.sourcefilepath, md.sourcefilename,
dc.classificationid, dc.classid, dc.userid
FROM MatterDataset md
LEFT JOIN DocumentClassification dc
ON dc.documentid = md.id
AND (dc.classid = 1 OR dc.classid = 2 )
AND dc.userid < 0
LEFT JOIN PrivilegeLog pl
ON md.id = pl.documentparentid
AND md.matterid = pl.matterid
WHERE pl.privilegelogitemid IS NULL
AND md.matterid = \'100\'
ORDER BY md.id LIMIT 1 ;
我不确定你是想要LEFT JOIN还是INNER JOIN到DocumentClassification(使用LEFT JOIN然后在WHERE语句中对classid和userid提出要求 - 在我看来 - 相互矛盾)。如果必须存在DocumentClassification,则更改为INNER JOIN并将对classid和userid的引用放入WHERE子句中,如果结果集中可能存在或不存在DocumentClassification,则按照我的建议保留查询。
答案 1 :(得分:0)
我回去重新开始。 SQL语法虽然在Java之外工作,但对于JDBC驱动程序而言似乎过于复杂。这个清理过的修订似乎有效:
SELECT DISTINCT
MatterDataset.id, MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath,
MatterDataset.sourcefilename
FROM MatterDataset , DocumentClassification
ON DocumentClassification.documentid = MatterDataset.id
AND MatterDataset.matterid = DocumentClassification.matterid
LEFT JOIN PrivilegeLog ON MatterDataset.id = PrivilegeLog.documentparentid
AND MatterDataset.matterid = PrivilegeLog.matterid
WHERE PrivilegeLog.privilegelogitemid IS NULL
AND MatterDataset.matterid = '100'
AND (DocumentClassification.classid = 1 OR DocumentClassification.classid = 2)
AND DocumentClassification.userid = -99
ORDER BY MatterDataset.id LIMIT 1;
一个很好的教训:仅仅因为你在SQL中并不意味着你应该这样做。
此语句的作用实质上是在MatterDataset表中找到不在PrivilegeLog表中的项。 LEFT JOIN和IS NULL语法定位缺少的项目。&#34;也就是说,我想找到在MatterDataset中但尚未在PrivilegeLog中的项目并返回这些项目。