簡體   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