从匿名块返回游标结果

Posted

技术标签:

【中文标题】从匿名块返回游标结果【英文标题】:Return cursor results from anonymous block 【发布时间】:2013-05-08 13:30:39 【问题描述】:

我有以下 SELECT ,我想将其更改为匿名块(需要像在 Java 中那样使用匿名块,并且无权访问创建的存储功能),以便将文字的使用删除到绑定变量:

SELECT IL.LAT_NUM, IL.LNGTD_NUM
FROM ITEM_LOCATION IL
WHERE IL.ITEM_ID = 294341;

我创建了两个匿名块,但无法找到如何返回两者中创建的值:

1)

DECLARE
    itemID number;
    latitude number;
    longitude number;
BEGIN
    itemID := 294341;

    SELECT 
        IL.LAT_NUM,
        IL.LNGTD_NUM,
    INTO
        latitude,
        longitude,
    FROM 
        ITEM_LOCATION IL
    WHERE 
        IL.ITEM_ID = itemID ;   
END;

2)

DECLARE
    TYPE t_ref_cursor IS REF CURSOR;
    c_cursor  t_ref_cursor;
    itemID number;
    latitude   ITEM_LOCATION.LAT_NUM%TYPE;
    longitude   ITEM_LOCATION.LNGTD_NUM%TYPE;
BEGIN
    itemID := 294341;

    OPEN c_cursor FOR
        SELECT 
            IL.LAT_NUM,
            IL.LNGTD_NUM, 
        FROM 
            ITEM_LOCATION IL
        WHERE 
            IL.ITEM_ID = itemID ; 
    CLOSE c_cursor; 
END;

有谁知道这两个块中的一个/两个如何像上面的 SELECT 一样返回?

【问题讨论】:

为什么不能将查询作为准备好的 statmenet 执行?在这些块中,您没有做任何不合时宜的事情。 你可以看看这个问题。 . . ***.com/questions/6455566/…. @haki - 我无权在应用程序的数据库上创建。公司的职责分离和 DBA 将无法很快实现。我想暂时修补它,直到 DBA 用准备好的语句回来。这是我认为不会花很长时间但已经成为一个真正的痛苦的事情。搜索的谷歌加载并且只能找到准备/存储功能的能力。许多文档谈论通过匿名块“返回”值,但与 DBMS_OUTPUT.put_line 相关。但这实际上并没有像 SELECT 那样返回值,它正在打印值。谢谢。 @Gordon Linoff - Pascal 试图调试块并且 DBMS_OUTPUT.put_line 工作,因为他只需要在控制台中查看数据,但我需要返回数据,就像执行了 SELECT 一样。谢谢。 @JamesGallagher:带有替换变量的 SQL Plus 脚本可以工作吗,例如 SELECT IL.LAT_NUM, IL.LNGTD_NUM FROM ITEM_LOCATION IL WHERE IL.ITEM_ID = &ITEMID; 【参考方案1】:

我想变成一个匿名块...为了删除 在绑定变量中使用文字

为什么你认为你需要使用匿名块来使用绑定变量?无论如何,您的两个块仍然具有硬编码的值294341;您的 select 在块中使用绑定变量,但每次都生成一个新块,这对您的改进有很大的改进吗?

正如@haki 几个小时前所说,您只需使用带有绑定变量的准备好的语句:

PreparedStatement pStmt = conn.prepareStatement(
    "SELECT IL.LAT_NUM, IL.LNGTD_NUM :
    + "FROM ITEM_LOCATION IL "
    + "WHERE IL.ITEM_ID = ?");
pStmt.setInt(1, 294341);

... 然后执行查询并按照您可能已经处理的方式处理结果集。 (从您对 haki 评论的回复来看,您似乎将准备好的语句(这是一种 Java/JDBC 构造)与数据库中的存储过程混淆了)。

这是一个针对演示 HR 架构的 EMP 表的简单独立示例:

导入 java.sql.; 导入 java.text.; 导入 oracle.jdbc.*; 导入 oracle.jdbc.pool.OracleDataSource;

public class JamesGallagher

    public static void main(String args[]) throws SQLException
    
        Connection conn;
        OracleDataSource ds = new OracleDataSource();
        ds.setURL("jdbc:oracle:thin:scott/oracle@127.0.0.1:1521:orcl");
        conn = ds.getConnection();

        PreparedStatement pStmt = conn.prepareStatement(
            "select ename, sal from emp where sal > ?");
        pStmt.setInt(1, Integer.parseInt(args[0]));

        ResultSet rs = pStmt.executeQuery();

        while (rs.next())
        
            System.out.println(rs.getString(1) + ": " + rs.getInt(2));
        

        try  rs.close();  catch ( Exception ex ) 
        try  pStmt.close();  catch ( Exception ex ) 
        try  conn.close();  catch ( Exception ex ) 
        conn = null;
    

我可以用javac JamesGallagher.java 编译它并用java JamesGallagher 1500 执行它,它会根据绑定值打印结果:

ALLEN: 1600
JONES: 2975
BLAKE: 2850
CLARK: 2450
SCOTT: 3000
KING: 5000
FORD: 3000

【讨论】:

感谢您的帖子。我希望不要进入“为什么”,因为它是冗长的。我正在使用 Apache SOLR 并且不支持准备好的语句 (issues.apache.org/jira/browse/SOLR-1262)。匿名块也可能不起作用,但我想尝试一下......我认为它会很快检查:) 变量是为上述 S.O. 硬编码的。示例,它们不会出现在实际代码中。绑定变量的原因:普通 SELECT 中的版本计数非常高,并且使用了大量数据库的共享池(300MB)。谢谢你的评论,我确实选错了@haki :)

以上是关于从匿名块返回游标结果的主要内容,如果未能解决你的问题,请参考以下文章

从 Oracle 函数返回一个表,在匿名块中定义

如何使用返回数据的回调函数设置匿名块

如何从 Oracle 过程返回填充了 NESTED RECORD 类型的游标

从 Oracle PL/SQL 匿名块填充 C# 数据表

匿名块游标,包括 group by 和 for update

从Oracle中的函数返回游标