【问题标题】:PostgreSQL stored procedure not workingPostgreSQL 存储过程不工作
【发布时间】:2015-03-13 03:25:19
【问题描述】:

我在 Postgres DBMS 中创建了一个存储过程和一个调用该过程的 Java 函数。

运行Java函数后我收到错误:

org.postgresql.util.PSQLException: L'indice de la colonne est hors limite : 1, nombre de colonnes : 0.
    at org.postgresql.core.v3.SimpleParameterList.registerOutParameter(SimpleParameterList.java:49)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.registerOutParameter(AbstractJdbc2Statement.java:1968)
    at org.postgresql.jdbc3.AbstractJdbc3Statement.registerOutParameter(AbstractJdbc3Statement.java:1511)
    at DAO.FournisseurDAO.getLastId(FournisseurDAO.java:192)
    at CONTROLLER.FournisseurController.getLastIdInDataBase(FournisseurController.java:96)
    at VIEW.FournisseurUi.spinnerProperties(FournisseurUi.java:183)
    at VIEW.FournisseurUi.componentsProperties(FournisseurUi.java:139)
    at VIEW.FournisseurUi.<init>(FournisseurUi.java:100)
    at VIEW.FournisseurUi$2.run(FournisseurUi.java:542)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

这是程序代码:

CREATE OR REPLACE FUNCTION getlastfournisseurid(OUT lastid integer)
  RETURNS integer AS
$BODY$
begin 
       select last_value into lastid from fournisseur_fournisseurid_seq ; 
end;
$BODY$
  LANGUAGE plpgsql;

功能代码如下:

public int getLastId() {
        String fournisseurLastId = "{ call getLastFournisseurId() }";
        int lastid = -1 ; 
        // Get Connection 
        Connection connecte = utility.DatabaseConnection.getInstance();

        try {
            // Create a  callableStatement
            CallableStatement clblStmt = connecte.prepareCall(fournisseurLastId);
            // Process query
            clblStmt.registerOutParameter(1, java.sql.Types.INTEGER);
            ResultSet result = clblStmt.executeQuery();
            result.next();
            lastid = clblStmt.getInt(1); 

            // close used resources             
            clblStmt.close();
        } catch (SQLException ex) {
            ex.printStackTrace();
            return -1 ; 
        } finally {
            try {
                if (connecte != null) {
                    connecte.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

            return lastid;
        }
    }

【问题讨论】:

  • 你到底遇到了什么错误?
  • 我已将错误添加到问题中
  • 您是否尝试过从 SQL 命令接口(psql 或 pgAdmin3 等)直接调用您的存储过程来查看它是否有效?
  • 是的,它可以从 pgAdmin3 完美运行:select getlastfournisseurid() ;

标签: java postgresql stored-procedures jdbc


【解决方案1】:

您应该与该函数的参数(实际上是它的返回值)进行通信,但您将调用定义为:

String fournisseurLastId = "{ call getLastFournisseurId() }";

您应该将其定义为:

String fournisseurLastId = "{ ? = call getLastFournisseurId() }";

否则,JDBC 无法将第一个占位符注册为 out 参数 - 那里没有可注册的占位符。

【讨论】:

  • 一个 OUT 参数是 not 应该传递给 plpgsql 函数。而是返回
  • @ErwinBrandstetter 对。更改了语法。
  • 不确定 JDBC / Java 端,但 Postgres 端现在已修复。你可能也想澄清你的第一句话。
【解决方案2】:

Postgres 函数就是:函数。无需使用 JDBC 的 CallableStatement,它是为 real 存储过程设计的。

您的功能也可以简化。不需要 PL/pgSQL 函数。一个简单的 SQL 函数就可以了:

CREATE OR REPLACE FUNCTION getlastfournisseurid()
  RETURNS integer AS
$BODY$
    select lastvalue from fournisseur_fournisseurid_seq; 
$BODY$
  LANGUAGE sql;

(这里假设fournisseur_fournisseurid_seq表中永远不会超过一行,如果有,则需要在select语句中添加limit 1

然后这样称呼它:

Statement stmt = connecte.createStatement();
ResultSet rs = stmt.executeQuery("select getlastfournisseurid()");
rs.next();
lastid = rs.getInt(1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    相关资源
    最近更新 更多