【问题标题】:How to fix the result consisted of more than one row error如何修复包含多行错误的结果
【发布时间】:2017-03-14 05:49:53
【问题描述】:

我在 MySQL 中编写了如下所示的存储过程(它可以工作):

DELIMITER //

CREATE PROCEDURE getBrandRows(
    IN pBrand VARCHAR(30),
    OUT pName VARCHAR(150),
    OUT pType VARCHAR(200),
    OUT pRetailPrice FLOAT)
BEGIN
    SELECT p_name, p_type, p_retailprice INTO pName, pType, pRetailPrice
    FROM part
    WHERE p_brand LIKE pBrand;
END//

DELIMITER ;

我尝试返回多个结果并显示它们。我已经尝试过 Stack 和 Internet 上描述的许多方法,但这对我没有帮助。我已经编辑了我的整个代码并创建了一个简单的代码,所以你们可以粘贴并编译它。它应该可以工作,但有错误。代码如下:

package javamysqlstoredprocedures;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

public class JavaMySqlStoredProcedures {

    private final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver";
    private final String DB_URL = "jdbc:mysql://anton869.linuxpl.eu:3306/" 
            + "anton869_cars?noAccessToProcedureBodies=true"; 
    private final String DB_USER = "xxx";
    private final String DB_PASSWORD = "xxx";

    class CallStoredProcedureAndSaveXmlFile extends SwingWorker<Void, Void> {

        @Override
        public Void doInBackground() {
            displaySql();
            return null;
        }

        @Override
        public void done() {
        }

        private void displaySql() {
        try {
            System.out.println("Connecting to MySQL database...");
            Class.forName(DEFAULT_DRIVER);
            try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, 
                    DB_PASSWORD)) {
                System.out.println("Connected to MySQL database");
                CallableStatement cs = conn.prepareCall("{CALL getBrandRows("
                        + "?, ?, ?, ?)}");
                cs.setString(1, "Brand#13");
                cs.registerOutParameter(2, Types.VARCHAR);
                cs.registerOutParameter(3, Types.VARCHAR);
                cs.registerOutParameter(4, Types.FLOAT);

                boolean results = cs.execute();
                while (results) {
                    ResultSet rs = cs.getResultSet();
                    while (rs.next()) {
                        System.out.println("p_name=" + rs.getString("p_name"));
                        System.out.println("p_type=" + rs.getString("p_type"));
                        System.out.println("p_retailprice=" + rs
                                .getFloat("p_retailprice"));
                    }
                    rs.close();
                    results = cs.getMoreResults();
                }
                cs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        }

    }

    public JavaMySqlStoredProcedures() {
         new CallStoredProcedureAndSaveXmlFile().execute();
    }

    public static void main(String[] args) {
        JavaMySqlStoredProcedures jmssp = new JavaMySqlStoredProcedures();
    }

}

【问题讨论】:

  • Result consisted of more than one row ...我认为问题在于存储过程中的查询返回了多个记录。你需要解决这个问题。我的快速解决方法是在查询末尾添加LIMIT 1,尽管逻辑上可能不正确。但是根据健全的业务逻辑,你最好添加限制为一条记录的逻辑。
  • 如何使用procedure.返回并操作多条记录。我第一次这样做。我的意思是我想从过程中获取多条记录,并像使用游标一样查看每一行。
  • 如果你能清楚地表达你想对多条记录做什么,那么也许有人可以帮助你。
  • 我的任务是在某些条件下使用存储过程从表中获取一些列。以为我可以使用多个输出从程序中获得多个结果。我只想使用存储过程获得与使用 SELECT 语句选择 3 列相同的效果。
  • 你的问题不是你选择了多少列,而是你选择了多少。具体来说,您选择的是多行,并且您无法在已定义的存储过程中执行此操作。

标签: java mysql stored-procedures jdbc


【解决方案1】:

ResultSet 可以处理多条记录。我在您的代码中发现了一些错误。请尝试以下步骤

  1. 将你的 all close 方法移动到 finally 块。

    try {
       //do something
    } catch (Exception e) {
       //do something
    } finally {
        try{
          resultSet.close();
          statement.close();
          connection.close();
        } catch (SQLException se) {
            //do something
        }
    }
    
  2. 您可以将结果放入列表中。查看示例

    List<YourObject> list = new ArrayList<YourObject>();
    while (rs.next()) {
       YourObject obj = new Your Object();
       obj.setName(rs.getString("p_name"));
       obj.setType(rs.getString("p_type"));
       obj.setRetailPrice(rs.getFloat("p_retailprice"));
       list.add(obj);
       }
    
  3. 确保您的查询正确且数据库连接正常。

【讨论】:

  • 您的解决方案帮助我解决了我的问题。谢谢!
【解决方案2】:

如果您只是想显示结果,请不要使用 IN 或 OUT 参数。此外,您还应该借助 CONCAT 函数在 LIKE 子句中添加 '%%'。请试试这个:

DELIMITER //

CREATE PROCEDURE getBrandRows(
    pBrand VARCHAR(30)
)

BEGIN

    SELECT p_name, p_type, p_retailprice INTO pName, pType, pRetailPrice
    FROM part
    WHERE p_brand LIKE CONCAT("%", pBrand, "%");

END//

DELIMITER ;

【讨论】:

  • 所以我所要做的就是删除输出并在过程中简单地使用 SELECT ?
  • 对于这种情况,是的。但是,如果您想从主体内部获取标量结果或聚合结果,如 SUM()、COUNT() 或类似结果,则可以使用 OUT 参数指定其返回值。
【解决方案3】:

我正在向所有有类似问题的人发布正确的解决方案:

1.更正的存储过程:

DELIMITER //

CREATE PROCEDURE getBrandRows(
    IN pBrand VARCHAR(30))
BEGIN
    SELECT p_name, p_type, p_retailprice 
    FROM part
    WHERE p_brand = pBrand;
END//

DELIMITER ;

2。更正的 Java 代码:

package javamysqlstoredprocedures;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

public class JavaMySqlStoredProcedures {

    private final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver";
    private final String DB_URL = "jdbc:mysql://anton869.linuxpl.eu:3306/" 
            + "anton869_cars?noAccessToProcedureBodies=true"; 
    private final String DB_USER = "xxx";
    private final String DB_PASSWORD = "xxx";

    class CallStoredProcedureAndSaveXmlFile extends SwingWorker<Void, Void> {

        @Override
        public Void doInBackground() {
            displaySql();
            return null;
        }

        @Override
        public void done() {
        }

        private void displaySql() {
            Connection conn = null;
            CallableStatement cs = null;
            ResultSet rs = null;
            try {
                System.out.println("Connecting to MySQL database...");
                Class.forName(DEFAULT_DRIVER);
                conn = DriverManager.getConnection(DB_URL, DB_USER, 
                        DB_PASSWORD);
                System.out.println("Connected to MySQL database");

                cs = conn.prepareCall("{CALL getBrandRows(?)}");
                cs.setString(1, "Brand#13");

                boolean results = cs.execute();
                while (results) {
                    rs = cs.getResultSet();
                    while (rs.next()) {
                        System.out.println("p_name=" + rs.getString("p_name"));
                        System.out.println("p_type=" + rs.getString("p_type"));
                        System.out.println("p_retailprice=" + rs.getFloat(
                                "p_retailprice"));
                    }
                    results = cs.getMoreResults();
                }
            } catch (SQLException | ClassNotFoundException e) {
            } finally {
                try {
                    if (rs != null ) rs.close();
                    if (cs != null) cs.close();
                    if (conn != null) conn.close();
                } catch (SQLException e) {
                }
            }
        }

    public JavaMySqlStoredProcedures() {
         new CallStoredProcedureAndSaveXmlFile().execute();
    }

    public static void main(String[] args) {
        JavaMySqlStoredProcedures jmssp = new JavaMySqlStoredProcedures();
    }

}

【讨论】:

    【解决方案4】:

    您的存储过程返回多行。只需在存储过程中正确选择查询背后的逻辑,它就应该只返回一行。

    here how to return multiple value

    【讨论】:

    • 但是如何使用返回多个数据集的存储过程对多条记录进行操作呢?
    猜你喜欢
    • 1970-01-01
    • 2011-01-15
    • 2023-03-21
    • 2018-03-07
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    相关资源
    最近更新 更多