Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql CallableStatement+;registerOutParameter+;多行结果_Sql_Oracle - Fatal编程技术网

Sql CallableStatement+;registerOutParameter+;多行结果

Sql CallableStatement+;registerOutParameter+;多行结果,sql,oracle,Sql,Oracle,我有一个SQL语句的形式: BEGIN\n UPDATE tab SET stuff WHERE stuff RETURNING intA, intB, stringC INTO ?,?,? 我已经注册了适当的输出参数 这里我有一些问题:我是调用stmt.executeQuery()还是调用stmt.execute()?此外,我知道通过一个普通的SELECT查询,我可以循环遍历resultSet并填充我的对象——多行Out参数的等价物是什么 编辑: 也许我可以注册一个类型为CURSOR的单

我有一个SQL语句的形式:

BEGIN\n 
UPDATE tab 
SET stuff
WHERE stuff
RETURNING intA, intB, stringC
INTO ?,?,?
我已经注册了适当的输出参数

这里我有一些问题:我是调用stmt.executeQuery()还是调用stmt.execute()?此外,我知道通过一个普通的SELECT查询,我可以循环遍历resultSet并填充我的对象——多行Out参数的等价物是什么

编辑: 也许我可以注册一个类型为CURSOR的单独参数,并在这个结果上循环

编辑2: 我可能有多个需要循环的结果集吗?
谢谢

要基于Luke Woodward的回答并完善我之前的回答,您可以创建一个Oracle类型,使用它临时存储数据,然后返回一个带有更新的sys_refcursor

创建新类型:

CREATE OR REPLACE TYPE rowid_tab AS TABLE OF varchar2(30);
创建数据库功能:

CREATE OR REPLACE
FUNCTION update_tab
RETURN sys_refcursor
IS
    ref_cur sys_refcursor;
    v_tab rowid_tab;
BEGIN
    UPDATE tab 
    SET intA = intA+2
      , intB = intB*2
      , stringC = stringC||' more stuff.'
    RETURNING ROWID
    BULK COLLECT INTO v_tab;

    OPEN ref_cur FOR 
        WITH DATA AS (SELECT * FROM TABLE(v_tab))
        SELECT intA, intB, stringC
        FROM tab
        where rowid in (select * from data);
    RETURN ref_cur;
END;
现在,在java中调用函数:

import java.math.BigDecimal;
import java.util.Arrays;
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.*;

public class StructTest {    
    public static void main(String[] args) 
        throws Exception 
    {   
        System.out.println("Start...");

        ResultSet results = null;
        Connection c = DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:xe", "scott", "tiger");
        c.setAutoCommit(false);        

        String sql = "begin ? := update_tab(); end;";
        System.out.println("sql = "+sql);
        CallableStatement stmt = c.prepareCall(sql);        
        /* Register the out parameter. */
        System.out.println("register out param");
        stmt.registerOutParameter(1, OracleTypes.CURSOR);
        // get the result set
        stmt.execute();
        results = (ResultSet) stmt.getObject(1);
        while (results.next()){
            System.out.println("intA: "+results.getString(1)+", intB: "+results.getString(2)+", stringC: "+results.getString(3));
        }
        c.rollback();        
        c.close();    
    }
}
根据我的测试数据,我得到了以下结果:

intA: 3, intB: 4, stringC: a more stuff.
intA: 6, intB: 10, stringC: C more stuff.
intA: 3, intB: 4, stringC: a more stuff.

我相信您可以实现所需的功能,但您需要处理PL/SQL数组,而不是游标或结果集。下面是一个演示

我有一个名为
TEST
的表,其结构如下:

SQL> desc test; Name Null? Type ----------------------------------------- -------- ----------------- A NUMBER(38) B NUMBER(38) C NUMBER(38) 我们只需要在数据库中设置表和任何必要的类型。完成之后,我们就可以编写一个简短的Java类来执行
更新。。。返回…
,将多个值返回到Java:

import java.math.BigDecimal;
import java.util.Arrays;
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.*;

public class UpdateWithBulkReturning {
    public static void main(String[] args) throws Exception {
        Connection c = DriverManager.getConnection(
            "jdbc:oracle:thin:@localhost:1521:XE", "user", "password");

        c.setAutoCommit(false);

        /* You need BULK COLLECT in order to return multiple rows. */
        String sql = "BEGIN UPDATE test SET a = a + 10 WHERE b <> 5 " +
                     "RETURNING a, b, c BULK COLLECT INTO ?, ?, ?; END;";

        CallableStatement stmt = c.prepareCall(sql);

        /* Register the out parameters.  Note that the third parameter gives
         * the name of the corresponding array type. */
        for (int i = 1; i <= 3; ++i) {
            stmt.registerOutParameter(i, Types.ARRAY, "T_INTEGER_ARRAY");
        }

        /* Use stmt.execute(), not stmt.executeQuery(). */
        stmt.execute();

        for (int i = 1; i <= 3; ++i) {
            /* stmt.getArray(i) returns a java.sql.Array for the output parameter in
             * position i.  The getArray() method returns the data within this
             * java.sql.Array object as a Java array.  In this case, Oracle converts
             * T_INTEGER_ARRAY into a Java BigDecimal array. */
            BigDecimal[] nums = (BigDecimal[]) (stmt.getArray(i).getArray());
            System.out.println(Arrays.toString(nums));
        }

        stmt.close();
        c.rollback();
        c.close();
    }
}
import java.math.BigDecimal;
导入java.util.array;
导入java.sql.*;
导入oracle.sql.*;
导入oracle.jdbc.*;
公共类UpdateWithBulkReturning{
公共静态void main(字符串[]args)引发异常{
连接c=DriverManager.getConnection(
“jdbc:oracle:thin:@localhost:1521:XE”,“user”,“password”);
c、 设置自动提交(错误);
/*您需要批量收集才能返回多行*/
String sql=“开始更新测试集a=a+10,其中b 5”+
“返回a、b、c批量收集到?、?、?;结束;”;
CallableStatement stmt=c.prepareCall(sql);
/*注册out参数。注意,第三个参数
*对应数组类型的名称*/

对于(int i=1;我将在另一个resultSet中获取返回值?我需要多行。抱歉,我以为您得到的是一行。对于多行,您可以打开一个ref游标来选择where子句标识的记录。但是,这可能会返回比您刚刚更新的更多行。这看起来确实是一种更好的方法韩:我的答案。+1谢谢,迈克尔——实际上我已经采用了卢克的解决方案——在这里向您推荐了tooThanks,将对此进行测试并报告——我在哪里可以找到sql限定类型的映射(对于日期等)嗯,因此这些类型将成为sql表脚本的一部分我假设下面是类型列表:到目前为止很好:)我想不可能打印出数据行=/(我有很多变量) SQL> create type t_integer_array as table of integer; 2 / Type created.
import java.math.BigDecimal;
import java.util.Arrays;
import java.sql.*;
import oracle.sql.*;
import oracle.jdbc.*;

public class UpdateWithBulkReturning {
    public static void main(String[] args) throws Exception {
        Connection c = DriverManager.getConnection(
            "jdbc:oracle:thin:@localhost:1521:XE", "user", "password");

        c.setAutoCommit(false);

        /* You need BULK COLLECT in order to return multiple rows. */
        String sql = "BEGIN UPDATE test SET a = a + 10 WHERE b <> 5 " +
                     "RETURNING a, b, c BULK COLLECT INTO ?, ?, ?; END;";

        CallableStatement stmt = c.prepareCall(sql);

        /* Register the out parameters.  Note that the third parameter gives
         * the name of the corresponding array type. */
        for (int i = 1; i <= 3; ++i) {
            stmt.registerOutParameter(i, Types.ARRAY, "T_INTEGER_ARRAY");
        }

        /* Use stmt.execute(), not stmt.executeQuery(). */
        stmt.execute();

        for (int i = 1; i <= 3; ++i) {
            /* stmt.getArray(i) returns a java.sql.Array for the output parameter in
             * position i.  The getArray() method returns the data within this
             * java.sql.Array object as a Java array.  In this case, Oracle converts
             * T_INTEGER_ARRAY into a Java BigDecimal array. */
            BigDecimal[] nums = (BigDecimal[]) (stmt.getArray(i).getArray());
            System.out.println(Arrays.toString(nums));
        }

        stmt.close();
        c.rollback();
        c.close();
    }
}
C:\Users\Luke\stuff>java UpdateWithBulkReturning [11, 17] [2, 8] [3, 9]