动态SQL游标和函数返回游标举例(转载)

本文提供了动态SQL游标在PL/SQL和Java中的使用实例,包括创建游标类型、调用过程获取数据并使用游标进行遍历。详细解释了如何在两种不同的编程环境中实现数据检索和输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态SQL游标的例子,来自: http://www.itpub.net/thread-257998-1-1.html
strSQL:='SELECT * FROM ' || tmp_tbl;
open c_sign_stat for strSQL;
 

函数返回游标的例子,来自:http://soft.zdnet.com.cn/software_zone/2009/1221/1568365.shtml

 
过程或函数能返回或out静态游标吗?
 
CREATE OR REPLACE PACKAGE Types AS 
  TYPE cursor_type IS REF CURSOR; 
END Types; 
/
 
CREATE OR REPLACE 
PROCEDURE GetEmpRS (p_deptno    IN  emp.deptno%TYPE, 
                    p_recordset OUT Types.cursor_type) AS 
BEGIN 
  OPEN p_recordset FOR 
    SELECT ename, 
          empno, 
          deptno 
    FROM  emp 
    WHERE  deptno = p_deptno 
    ORDER BY ename; 
END GetEmpRS; 
/
 
 
在pl/sql中使用: 
SET SERVEROUTPUT ON SIZE 1000000 
DECLARE 
  v_cursor  Types.cursor_type; 
  v_ename  emp.ename%TYPE; 
  v_empno  emp.empno%TYPE; 
  v_deptno  emp.deptno%TYPE; 
BEGIN 
  GetEmpRS (p_deptno    => 30, 
            p_recordset => v_cursor); 
            
  LOOP 
    FETCH v_cursor 
    INTO  v_ename, v_empno, v_deptno; 
    EXIT WHEN v_cursor%NOTFOUND; 
    DBMS_OUTPUT.PUT_LINE(v_ename || ' | ' || v_empno || ' | ' || v_deptno); 
  END LOOP; 
  CLOSE v_cursor; --记得close游标,add by valleylord
END; 
/
 
在java中使用: 
import java.sql.*; 
import Oracle.jdbc.*;
 
public class TestResultSet  { 
  public TestResultSet() { 
    try { 
      DriverManager.registerDriver (new Oracle.jdbc.OracleDriver()); 
      Connection conn = DriverManager.getConnection("jdbc:Oracle:oci:@w2k1", "scott", "tiger"); 
      CallableStatement stmt = conn.prepareCall("BEGIN GetEmpRS(?, ?); END;"); 
      stmt.setInt(1, 30); // DEPTNO 
      stmt.registerOutParameter(2, OracleTypes.CURSOR); //REF CURSOR 
      stmt.execute(); 
      ResultSet rs = ((OracleCallableStatement)stmt).getCursor(2); 
      while (rs.next()) { 
        System.out.println(rs.getString("ename") + ":" + rs.getString("empno") + ":" + rs.getString("deptno")); 
      } 
      rs.close(); 
      rs = null; 
      stmt.close(); 
      stmt = null; 
      conn.close(); 
      conn = null; 
    } 
    catch (SQLException e) { 
      System.out.println(e.getLocalizedMessage()); 
    } 
  }
 
  public static void main (String[] args) { 
    new TestResultSet(); 
  } 
}
 
 

转载于:https://www.cnblogs.com/valleylord/archive/2012/11/07/2758784.html

<think>好的,我现在需要解释存储过程游标,还要举例说明。首先,我得回忆一下存储过程的基本概念。存储过程是预先编译的SQL代码块,可以重复使用,对吧?它们通常用来封装复杂的操作,提高性能,减少网络传输。比如,用户可能调用一个存储过程来执行一系列插入、更新操作,而不是发送多个SQL语句。 然后是游标游标应该是对结果集的一种处理机制,允许逐行处理数据。普通的SQL操作是面向集合的,但有时候需要逐行处理,这时候游标就派上用场了。不过游标可能会影响性能,因为逐行操作比集合操作慢。 接下来要举例子。存储过程的例子可能是一个简单的插入或者计算过程。比如创建一个存储过程来根据部门统计员工数量。那游标的例子可能需要遍历某个结果集,比如逐行处理员工表,根据条件更新奖金或者其他字段。 需要注意的是,存储过程的优点包括模块化、提高性能、减少网络流量,以及增强安全性。而缺点可能是数据库依赖,维护成本。游标的优点在于处理复杂逻辑,但缺点就是性能问题,尤其是在大数据量时。 在写例子的时候,要确保语法正确。比如创建存储过程的语法是CREATE PROCEDURE,里面包含BEGINEND。使用DECLARE来定义变量,循环处理可能需要用到WHILE或者REPEAT。游标的使用步骤包括声明、打开、获取、关闭、释放。 可能用户容易混淆存储过程函数的区别,存储过程没有返回值,函数有。但这里问题没提到函数,所以可能不需要展开。另外,游标的使用步骤容易出错,比如忘记关闭或释放,导致资源占用。 还需要注意例子中的具体SQL写法是否符合不同数据库的规范,比如MySQLSQL Server可能在语法细节上有差异。这里可能需要选择一个通用的写法,或者说明可能因数据库而异。 最后,总结存储过程游标的适用场景,以及它们的优缺点。确保回答结构清晰,分点说明,举例恰当。</think>### 一、存储过程的理解 1. **定义** 存储过程是预编译的SQL语句集合,存储在数据库中,可被多次调用。类似编程中的函数,支持输入参数、逻辑控制(条件判断、循环)输出结果。 2. **核心特点** - **预编译执行**:首次执行时编译,后续调用直接使用编译后的计划,提高性能 - **减少网络开销**:封装多步操作为一个单元,避免逐条传输SQL语句 - **权限控制**:通过授权存储过程访问而非底层表,增强安全性 3. **示例** 统计指定部门员工数量的存储过程: ```sql CREATE PROCEDURE GetEmployeeCount( IN dept_name VARCHAR(50), OUT total INT ) BEGIN SELECT COUNT(*) INTO total FROM employees WHERE department = dept_name; END ``` 调用方式: ```sql CALL GetEmployeeCount('Sales', @count); SELECT @count; ``` --- ### 二、游标的理解 1. **定义** 游标是一种数据库对象,用于逐行遍历查询结果集。适用于需要对结果集进行逐行处理的场景。 2. **核心特点** - **逐行操作**:突破SQL集合操作的局限 - **资源消耗**:占用较多内存,大数据量时可能引发性能问题 - **典型步骤**:声明 → 打开 → 逐行读取 → 关闭 3. **示例** 使用游标批量更新员工奖金: ```sql CREATE PROCEDURE UpdateBonuses() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE emp_id INT; DECLARE salary DECIMAL(10,2); -- 声明游标 DECLARE cur CURSOR FOR SELECT employee_id, salary FROM employees; -- 声明结束处理器 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; read_loop: LOOP FETCH cur INTO emp_id, salary; IF done THEN LEAVE read_loop; END IF; -- 根据薪资计算奖金 IF salary > 10000 THEN UPDATE employees SET bonus = salary * 0.1 WHERE employee_id = emp_id; ELSE UPDATE employees SET bonus = salary * 0.05 WHERE employee_id = emp_id; END IF; END LOOP; CLOSE cur; END ``` --- ### 三、对比总结 | **特性** | 存储过程 | 游标 | |-----------------|----------------------------|--------------------------| | **操作对象** | 封装完整业务逻辑 | 处理查询结果集的单行数据 | | **性能** | 高效(预编译、批量操作) | 较低(逐行处理消耗资源) | | **典型场景** | 数据清洗、复杂报表生成 | 逐行校验、基于行的计算 | > **注意**:游标应作为最后手段使用,优先考虑集合操作(如`UPDATE...CASE`替代上述游标示例)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值