SQL查询不会执行SQLite,Java

时间:2012-07-14 18:04:18

标签: java sql sqlite jdbc

问题简介: 尝试使用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 ;") ;

2 个答案:

答案 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中的项目并返回这些项目。