无法对 PLSQL 语句执行提取

Cannot perform fetch on a PLSQL statement

这是我的table

CREATE TABLE accounts (
    accountid        VARCHAR(255),
    name             VARCHAR2(255),
    phone_number     INTEGER,
    email_addresses  VARCHAR2(255),
    account_number   VARCHAR(255),
    password         VARCHAR2(255)
);

现在我创建了一个程序

create or replace PROCEDURE getaccount (
    param1 IN VARCHAR2
) AS
BEGIN
 DBMS_OUTPUT.PUT_LINE('   SELECT
        accountid,
        password
    FROM
        accounts
    WHERE
        account_number = '||param1) ;
END getaccount;

以及为什么我们使用 ||或运算符

second i 运行 SQLDEVELOPER 中的这段代码 我把这个弄出来

call getaccount('123456');

Call completed.

收到此消息

现在我正在连接 JAVA 这是我的代码 JAVA

CallableStatement pst = Get.connection().prepareCall("{call getAccount(?)}");
                pst.setString(1, Number);
                ResultSet rs = pst.executeQuery();
                if (rs.next()) {
                    System.out.println(rs.getString(1));    

这里 Get.connection return 连接 .

在我 运行 之后我得到这个错误

Enter Account Number                       : 123456
java.sql.SQLException: Cannot perform fetch on a PLSQL statement: next
    at ojdbc10/oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:409)
    at bank.services.SignValidator.getBank(SignValidator.java:20)
    at bank.services.KingobankMain.getBank(KingobankMain.java:49)
    at bank.services.KingobankMain.main(KingobankMain.java:14)

我不知道 Java,但是:您编写的过程会导致屏幕上显示输出,但前提是您用来调用该过程的工具支持它 - 例如SQL*另外,SQL 开发人员、TOAD 等。剩下的,根本不会有结果。

看起来你想要运行

select accountid, password from accoutns where account_number = 123456

在 Java。然后,您应该使用 function 而不是过程。它应该 return 一个 VARCHAR2 (那个 select 语句)然后你会在 Java 中执行它。如何?说不出来;正如我所说,我不知道 Java。在 Oracle 中,您将使用动态 SQL.

或者,如果它必须是一个过程,那么它应该有一个 OUT 参数,以便它 return 向调用者发送 select 语句。但是,调用者必须有“东西”(一个变量?)来接受那个输出。


根据您的要求,带有 OUT 参数的程序:

CREATE OR REPLACE PROCEDURE getaccount (param1     IN     VARCHAR2,
                                        par_query     OUT VARCHAR2)
AS
BEGIN
   par_query :=
         'SELECT  accountid,  password  FROM  accounts WHERE '
      || ' account_number = '
      || DBMS_ASSERT.enquote_literal (param1);
END getaccount;

注释dbms_assert,用于防止SQL注入。


为了在 Oracle 中 运行 它,您必须使用一个 PL/SQL 块和一个接受该过程 return 编辑的结果的变量。

SQL> set serveroutput on
SQL>
SQL> create or replace procedure getaccount (param1     in     varchar2,
  2                                          par_query     out varchar2)
  3  as
  4  begin
  5     par_query :=
  6           'SELECT  accountid,  password  FROM  accounts WHERE '
  7        || ' account_number = '
  8        || dbms_assert.enquote_literal (param1);
  9  end getaccount;
 10  /

Procedure created.

SQL> declare
  2    l_out varchar2(200);
  3  begin
  4    getaccount('12345', l_out);
  5    dbms_output.put_line('Result is: ' || l_out);
  6  end;
  7  /
Result is: SELECT  accountid,  password  FROM  accounts WHERE  account_number = '12345'

PL/SQL procedure successfully completed.

SQL>

显然,您不想 return 表示为字符串的命令,而是 select 语句产生的结果。正如所评论的,考虑 returning 一个 refcursor。此外,使用函数而不是过程;它们旨在“return”一个值。如果它是一个过程,则必须创建 OUT 参数并将它们的值接受到 something(可能是局部变量)。

假设这是table的内容:

SQL> select * From accounts;

 ACCOUNTID PASSWORD   ACCOUNT_NUMBER
---------- ---------- --------------------
         1 my_pwd     12345

SQL>

returns refcursor 的函数:

SQL> create or replace function getaccount (param1 in varchar2)
  2    return sys_refcursor
  3  is
  4    l_rc sys_refcursor;
  5  begin
  6    open l_rc for
  7           'SELECT  accountid,  password  FROM  accounts WHERE '
  8        || ' account_number = '
  9        || dbms_assert.enquote_literal (param1);
 10    return l_rc;
 11  end getaccount;
 12  /

Function created.

SQL> select getaccount('12345') from dual;

GETACCOUNT('12345')
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

 ACCOUNTID PASSWO
---------- ------
         1 my_pwd


SQL>

或者,具有 2 个 OUT 参数的过程:

SQL> create or replace procedure getaccount
  2    (param1  in  varchar2,
  3     p_accid out varchar2,
  4     p_pwd   out varchar2) is
  5  begin
  6    select accountid,  password
  7      into p_accid, p_pwd
  8    from  accounts
  9    where account_number = param1;
 10  end;
 11  /

Procedure created.

SQL> set serveroutput on
SQL> declare
  2    l_id  varchar2(20);
  3    l_pwd varchar2(20);
  4  begin
  5    getaccount('12345', l_id, l_pwd);
  6    dbms_output.put_line('ID = ' || l_id ||', PWD = ' || l_pwd);
  7  end;
  8  /
ID = 1, PWD = my_pwd

PL/SQL procedure successfully completed.

SQL>

您的程序没有 return 值(输出变量),您正在尝试获取数据。 这会导致错误。

存储过程输出参数:

reate or replace procedure getaccount (
    p_account_number  in varchar2,
    p_account_id      out varchar2,
    p_password        out varchar2  
) as
  
begin
     select
        accountid,
        password
     into 
        p_account_id,
        p_password
     from
        accounts
     where
        account_number = p_account_number ; 
end getaccount;
/

CallableStatement pst = Get.connection().prepareCall("{call getAccount(?,?,?)}");
                pst.setString(1, "....");//set account number
                pst.registerOutParameter(2, OracleTypes.VARCHAR);
                pst.registerOutParameter(3, OracleTypes.VARCHAR);               
                pst.execute();
        //read the OUT parameter now
                    
                System.out.println("AccountID="+pst.getString(2)+",password="+pst.getString(3));

..........your  of code....

存储过程 Oracle SYS_REFCURSOR:

create or replace procedure getaccount (
    p_account_number in varchar2,
    p_cur            out sys_refcursor
) as
  
begin
 open p_cur for 
 select
        accountid,
        password
    from
        accounts
    where
        account_number = p_account_number ;
end getaccount;
/

CallableStatement pst = Get.connection().prepareCall("{call getAccount(?,?)}");
                pst.setString(1, ".....");// set account number
                pst.registerOutParameter(2, OracleTypes.CURSOR);
                pst.execute();
        //read the OUT parameter now
            rs = (ResultSet) pst.getObject(2);
            
            while(rs.next()){
                System.out.println("AccountID="+rs.getString("accountid")+",password="+rs.getString("password"));
..........your  of code....
}

添加链接:

JDBC Basics

Calling PL/SQL from Java