繁体   English   中英

SQL查询将不会执行SQLite,Java

[英]SQL Query Will Not Execute SQLite, Java

问题摘要:尝试在Java中使用SQLite数据库执行SQL查询时,SQL语句无法从execute()或executeQuery()方法返回。 换句话说,系统在执行此SQL语句时“挂起”。

问题:我在做错什么来解释为什么ResultSet永不“返回”?

TroubleShooting我试图缩小问题的范围,而问题似乎出在Java的execute()或executeQuery()上。 ResultSet似乎永远不会返回。 例如,我尝试直接在SQLite中执行完全相同的查询(即使用SQLite数据库管理器)。 该查询(Java外部)在大约5毫秒内执行并返回有效的结果集。

注意:不会引发任何异常。 该系统似乎只是“挂起”,在手动杀死之前一直没有响应。 (等待超过10分钟。)

代码:我对代码进行了大量编辑,以使问题更易于查看。 (在生产中,这使用Prepared Statements。但是,在这两种方法中都会发生错误,即直接Statement和Prepared Statement版本。)

基本上,SELECT返回单个DB项目,以便用户可以查看该项目。

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驱动程序= Xerial sqlite-jdbc-3.7.2,SQLite 3,Windows

更新次要修订版:随着我继续对此进行处理,在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 ;") ;

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,则按照我上面的建议保留查询。

我回去,重新开始。 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语法查找“丢失”的项目。 也就是说,我想查找位于MatterDataset中但尚未在PrivilegeLog中的项目并返回这些项目。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM