具有多结果子查询的查询不适用于 jdbc

Posted

技术标签:

【中文标题】具有多结果子查询的查询不适用于 jdbc【英文标题】:query with multiple-result subquery not working with jdbc 【发布时间】:2017-07-03 06:18:50 【问题描述】:

我这几天一直在研究这个特定问题,但找不到任何解决方案。因此,我在这里。

情况:

表 1 列出了系统上的所有 JBoss 表 2 描绘了 JBoss 和 JBoss 的 1:n 关系,因为任何给定的 JBoss 都可以拥有一个或多个与其“对话”的 JBoss。 我有一个带有 JDBC 的 Java servlet 来连接到数据库并发出查询和 .jsp 页面来显示结果

编辑:

我打算对查询做什么:我的 servlet 正在尝试显示连接到给定 jboss 的所有信息。用户从 jsp 页面的 jboss 名称列表中选择一个 jboss。然后执行查询,出现错误。

EDIT2:

在测试小程序时将查询更改为内部子选择为where in 会导致相同的错误

EDIT4:

尝试使用查询作为脚本创建视图,然后尝试使用 select * from vtest 从创建的视图中获取所有条目,但没有成功。

问题:

当我尝试使用 servlet 运行以下 select 时,会导致 ORA-01427。如果我在 Toad for Oracle 中运行此语句,我会得到想要的结果。

select * from table1 where number in (
select jboss2 from table2 where jboss1 = (
select number from table1 where name = 'nam1'))

问题: 查询中是否缺少某些内容?即使查询本身是正确的,jdbc 是否可能无法处理具有多行结果的子查询?

表 1:

+--------+------+-----------+
| Number | Name | values... |
+--------+------+-----------+
| 000001 | nam1 | vals1     |
| 000002 | nam2 | vals2     |
| 000003 | nam3 | vals3     |
+--------+------+-----------+

表 2:

+--------+--------+
| JBoss1 | JBoss2 |
+--------+--------+
| 000001 | 000002 |
| 000001 | 000003 |
| 000002 | 000003 |
+--------+--------+

Toad 中的结果/所需结果:

+--------+------+-----------+
| Number | Name | values... |
+--------+------+-----------+
| 000002 | nam2 | vals2     |
| 000003 | nam3 | vals3     |
+--------+------+-----------+

EDIT3:

相关的 Java 类。省略不相关的查询。

class QuickInfoAction implements Action

    @Override
    public String execute(HttpServletRequest request, HttpServletResponse response) throws ActionException 
        Connection conn = null;
        PreparedStatement prep = null;
        ResultSet rs = null;
        Map<String,String> queries = Queries.getInfoQueries(request);

        try 
            conn = DatabaseConnector.getConnection();
            Map<String, Result> res = new HashMap<String, Result>();
            for (Map.Entry<String, String> entry: queries.entrySet()) 
                prep = conn.prepareStatement(entry.getValue()); 
                rs = prep.executeQuery();

                while(rs.next()) 
                    res.put(entry.getKey(), ResultSupport.toResult(rs));
                       
            

            request.setAttribute("results", res);

         catch (Exception e) 
            throw new ActionException(e.getStackTrace().toString());
         finally 
            try 
                conn.close();
                prep.close();
                rs.close();
             catch (Exception e) 
                throw new ActionException(e.getStackTrace().toString());
            
        

        return "results";
    




public static Map<String, String> getInfoQueries(HttpServletRequest request) 
    String jboss_res = "select jboss.name, jboss.port, jboss.apache_nummer, jboss.bere_mandant_id, "
            + "maschine.name as maschine, maschine.ip_adresse "
            + "from jboss "
            + "inner join maschine on jboss.maschine_nummer = maschine.nummer "
            + "where jboss.name = '" + request.getParameter("jboss") + "'";

    String jboss_db = "select datenbank.nummer, datenbank.name, db_schema.name as schema "
            + "from datenbank "
            + "inner join db_schema on datenbank.db_schema_nummer = db_schema.nummer "
            + "where datenbank.nummer = ("
                + "select datenbank_nummer "
                + "from jboss_datenbank "
                + "where jboss_nummer = ("
                    + "select nummer "
                    + "from jboss "
                    + "where name = '" + request.getParameter("jboss") + "'))";

    String jboss_tux = "select tuxedo.*, datenbank.name as datenbank, db_schema.name as schema "
            + "from tuxedo, datenbank,db_schema "
            + "where tuxedo.nummer = ("
                + "select tuxedo_nummer "
                + "from jboss "
                + "where name = '" + request.getParameter("jboss") + "') "
            + "and datenbank.nummer = ("
                + "select datenbank_nummer "
                + "from tuxedo_datenbank "
                + "where tuxedo_nummer = tuxedo.nummer) "
            + "and db_schema.nummer = ("
                + "select db_schema_nummer "
                + "from datenbank "
                + "where nummer = ("
                    + "select datenbank_nummer "
                    + "from tuxedo_datenbank "
                    + "where tuxedo_nummer = tuxedo.nummer))";
    String jboss_corr = "select * from jboss where nummer in ("
                + "select jboss_nummer_2 from jboss_corr where jboss_nummer_1 in ("
                + "select nummer from jboss where name = '" + request.getParameter("jboss") + "'))";

    Map<String, String> queries = new HashMap<String,String>();
    queries.put("jboss", jboss_res);
    queries.put("datenbank", jboss_db);
    queries.put("tuxedo", jboss_tux);
    queries.put("corr", jboss_corr);

return queries;

错误信息

03.07.2017 11:49:29,863 +0200 WARN  [at.itsv.ta2mig.jdbc.TA2MigOracleJDBCConnection] (hs0903 http-/0.0.0.0:8080-2)    ORA-01427: Unterabfrage für eine Zeile liefert mehr als eine Zeile

03.07.2017 11:49:29,864 +0200 INFO  [stdout] (hs0903 http-/0.0.0.0:8080-2)    error executing action

03.07.2017 11:49:29,864 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)    dbgr.exception.ActionException: [Ljava.lang.StackTraceElement;@46708550

03.07.2017 11:49:29,864 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at dbgr.action.QuickInfoAction.execute(QuickInfoAction.java:43)

03.07.2017 11:49:29,864 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at dbgr.servlet.ControllerServlet.doGet(ControllerServlet.java:28)

03.07.2017 11:49:29,865 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at dbgr.servlet.ControllerServlet.doPost(ControllerServlet.java:39)

03.07.2017 11:49:29,865 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)

03.07.2017 11:49:29,865 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)

03.07.2017 11:49:29,865 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295)

03.07.2017 11:49:29,865 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)

03.07.2017 11:49:29,865 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:231)

03.07.2017 11:49:29,866 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149)

03.07.2017 11:49:29,866 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169)

03.07.2017 11:49:29,866 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:150)

03.07.2017 11:49:29,866 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97)

03.07.2017 11:49:29,866 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102)

03.07.2017 11:49:29,866 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)

03.07.2017 11:49:29,866 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:854)

03.07.2017 11:49:29,867 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653)

03.07.2017 11:49:29,867 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:926)

03.07.2017 11:49:29,867 +0200 ERROR [stderr] (hs0903 http-/0.0.0.0:8080-2)      at java.lang.Thread.run(Thread.java:744)

【问题讨论】:

这似乎是问题所在:select number from table1 where name = 'nam1' ...您确定两个地方的基础数据相同吗? @harlequin:请告诉您查询背后的确切要求是什么?您想通过查询实现什么?可能您的查询本身可以简化并与 java 轻松集成。 您能否解释一下您对基础数据的含义以及为什么这个select 会成为问题? 我并不是说现有的查询会是问题所在。我只是问您查询的确切要求是什么?是否像获取具有 name=nam1 的 JBoss 与之交谈的所有 JBoss 的详细信息? 如果错误信息可信的话,我指出的子查询返回了多个记录。您需要找出发生这种情况的原因。 【参考方案1】:

似乎你也需要一个用于内部子选择的地方

select * from table1 where number in (
  select jboss2 from table2 where jboss1 in (
    select number from table1 where name = 'nam1'))

【讨论】:

我尝试过像这样更改内部选择但无济于事。它仍然导致相同的错误 检查得更好.. 错误 ORA-01427。是为了返回更多的行和 th 在 clasue 必须解决这个问题【参考方案2】:

不确定为什么带有 where-in 的查询对您不起作用,但这里有一个查询,其中第二个子查询被替换为连接:

select * from table1 where number in (
  select jboss2 from table2
  join table1 on table2.jboss1 = table1.number
    and table1.name = 'nam1'
)

【讨论】:

感谢查询版本,但不幸的是我仍然遇到同样的错误。【参考方案3】:

我找到了解决方案。另一个查询也返回了多个结果。此查询不是为此而设计的,因此失败了。这是我的疏忽。

【讨论】:

以上是关于具有多结果子查询的查询不适用于 jdbc的主要内容,如果未能解决你的问题,请参考以下文章

如果子查询没有返回结果,为啥“= ALL(子查询)”评估为真?

EXISTS 不适用于 WITH 子句中的子查询

为啥排序规则不适用于子查询中的 xml 路径?

SQL Server:表值函数不适用于子查询

(My)SQL:如果子查询不是空集,则返回子查询

查询适用于 phpMyAdmin,但不适用于 Java [重复]