数据库游标:使用方法及优化技巧 (关于数据库游标)

在进行数据库操作的时候,我们经常需要对一些数据进行遍历、修改或删除的操作。传统的SQL语句虽然可以实现这些操作,但是往往需要写较为复杂的SQL语句。此时,数据库游标就派上了用场。数据库游标是一种用于对数据库中记录集进行遍历的机制。本文将详细介绍数据库游标的使用方法及优化技巧。

一、数据库游标的基本使用方法

1.1 游标的定义

游标是一种用于对数据库中记录集进行遍历的机制。定义游标也就是为了方便在结果集上进行遍历及修改等操作。SQL语句查询所得的结果集一般不允许直接修改,而游标可以实现对结果集的逐行遍历并执行修改操作。

1.2 游标的声明

声明游标有两部分组成:DECLARE CURSOR 和 SELECT 语句。游标可以在SELECT语句中进行参数设置、数据过滤等操作。

DECLARE CURSOR MyCursor

AS

SELECT *

FROM MyTable

WHERE MyTable.MyColumn >= 100;

1.3 游标的打开和关闭

当一个游标被声明之后,就可以使用“OPEN”命令来打开它。游标的打开方式是使用“FETCH NEXT”命令,该命令可以获取游标的下一行数据。当游标处理结束后,使用“CLOSE”命令来关闭游标。

OPEN MyCursor;

FETCH NEXT FROM MyCursor;

CLOSE MyCursor;

1.4 游标的使用

在遍历游标的过程中,我们可以使用“FETCH NEXT”命令来获取下一行数据。使用“WHILE”循环来遍历所有记录,并执行相应的修改操作。

DECLARE @ID INT, @Name VARCHAR(50);

OPEN MyCursor;

FETCH NEXT FROM MyCursor INTO @ID, @Name;

WHILE (@@FETCH_STATUS = 0)

BEGIN

UPDATE MyTable SET MyColumn = MyColumn + 1

WHERE ID = @ID AND Name = @Name;

FETCH NEXT FROM MyCursor INTO @ID, @Name;

END

CLOSE MyCursor;

1.5 游标的删除

删除游标的时候,我们需要使用“DEALLOCATE”命令。

DEALLOCATE MyCursor;

二、数据库游标的优化技巧

2.1 避免在游标中进行大量数据操作

游标可以一行一行地处理数据,但是每次遍历只能处理一条数据,对于大量数据的操作,处理效率会很低。因此,在处理大量数据时,应该尽量避免使用游标。

2.2 避免在游标中进行查询操作

在游标中进行查询操作会引起性能问题。如果查询语句中使用了不恰当的索引或者没有索引,则查询的速度将会很慢。因此,在游标中尽量减少查询次数,或者使用更佳的查询方案。

2.3 游标的过滤

在定义游标的时候,使用WHERE语句可以对游标所遍历的记录进行过滤,从而提高游标的处理效率。

DECLARE CURSOR MyCursor

AS

SELECT *

FROM MyTable

WHERE MyTable.MyColumn >= 100;

2.4 游标的批量处理

当需要进行批量处理时,可以使用游标遍历数据并将其存储在临时表中,然后使用一次SQL语句批量更新。

SET NOCOUNT ON;

DECLARE @ID INT, @Name VARCHAR(50);

CREATE TABLE #TempTable (ID INT, Name VARCHAR(50));

INSERT INTO #TempTable (ID, Name)

SELECT ID, Name

FROM MyTable

WHERE MyColumn >= 100;

UPDATE MyTable

SET MyColumn = MyColumn + 1

WHERE EXISTS (SELECT * FROM #TempTable WHERE MyTable.ID = #TempTable.ID AND MyTable.Name = #TempTable.Name);

DROP TABLE #TempTable;

本文介绍了数据库游标的基本使用方法及优化技巧。游标用于对结果集进行逐行遍历、修改、删除等操作。在使用游标时,应该尽量避免在游标中进行大量的数据操作和查询操作。同时,游标的过滤和批量处理可以有效提高游标的处理效率。

相关问题拓展阅读:

数据库游标

嗯,update yx1 set age=’2′ where current of tc2 有语法错误,用楼上的就可以修改

把declare tc2 SCROLL cursor for

select * from yx1

for update

的锋腔“for update ”去笑纯掉

应该是where 字段名=条件银升衫

你创枝弊建的这个表 yx1 没有主键或者unique约束,current of tc2 找不到。因此会报

消息友搭肆 16929,级别 16 状态 1,第 6 行

游标是只读的。

这个错误。

改正这个错误 1.对这个表创建主键约束

2.更新条件好轿 换做 楼上的 where 条件。

of 是什么猜则东西 我怎么穗卖棚没用到过呢

更新条件 update cardinfo set isreportloss=’是’where cardid=’ 1134’配山

快速掌握Oracle数据库游标的使用方法

显式游标

  当查询返回结果超过一行时 就需要一个显式游标 此时丛氏消用户不能使用select into语句 PL/SQL管理隐式游标 当查询开始时隐式游标打开 查询结束时隐式游标自动关闭 显式游标在PL/SQL块的声明部分声明 在执行部分或异常处理部分打开 取出数据 关闭

  

   使用游标

  这里要做一个声明 我们所说的游标通常是指显式游标 因此从现在起没有特别指明的情况 我们所说的游标都是指显式游标 要在程序中使用游标 必须首先声明游标

  

   声明游标

  语法

  

  CURSOR cursor_name IS select_statement;

  在PL/SQL中游标名是一个未声明变量 不能给游标名赋值或用于表达式中

  

  例

  

  DELCARE CURSOR C_EMP IS SELECT empno ename salary FROM emp WHERE salary> ORDER BY ename; BEGIN

  在游标定义中SELECT语句中不一定非要表可以是视图 也可核态以从多个表或视图中选择的列 甚至可以使用*来选择所有的列

   打开游标

  使用游标中的值之前应该首先打开游标 打开游标初始化查询处理 打开游标的语法是

  

  OPEN cursor_name

  cursor_name是在声明部分定义的游标名

  

  例

  OPEN C_EMP; 关闭游标

  语法

  CLOSE cursor_name

  

  例

  CLOSE C_EMP; 从游标提取数据 从游标得到一行数据使用FETCH命令 每一次提取数据后 游标都指向结果集的下一行 语法如下

  FETCH cursor_name INTO variable

  对于SELECT定义的游标的每一列 FETCH变量列表都应该有一个变量与之相对应 变量的类型也要相同

  

  

  

  例

  

  SET SERVERIUTPUT ON DECLARE v_ename EMP ENAME%TYPE; v_salary EMP SALARY%TYPE; CURSOR c_emp IS SELECT ename salary FROM emp; BEGIN OPEN c_emp; FETCH c_emp INTO v_ename v_salary; DBMS_OUTPUT PUT_LINE( Salary of Employee || v_ename || is || v_salary); FETCH c_emp INTO v_ename v_salary; DBMS_OUTPUT PUT_LINE( Salary of Employee || v_ename || is || v_salary); FETCH c_emp INTO v_ename v_salary; DBMS_OUTPUT PUT_LINE( Salary of Employee || v_ename || is || v_salary); CLOSE c_emp; END

  这段代码无疑是非常麻烦的 如果有多行返回结果 可以使用循环并用游标属性为结束循环的条件 以这种方式提取数据 程序的可读性和简洁性都大渗知为提高 下面我们使用循环重新写上面的程序

  

  SET SERVERIUTPUT ON DECLARE v_ename EMP ENAME%TYPE; v_salary EMP SALARY%TYPE; CURSOR c_emp IS SELECT ename salary FROM emp; BEGIN OPEN c_emp; LOOP FETCH c_emp INTO v_ename v_salary; EXIT WHEN c_emp%NOTFOUND; DBMS_OUTPUT PUT_LINE( Salary of Employee || v_ename || is || v_salary); END

   记录变量

  定义一个记录变量使用TYPE命令和%ROWTYPE 关于%ROWsTYPE的更多信息请参阅相关资料

  记录变量用于从游标中提取数据行 当游标选择很多列的时候 那么使用记录比为每列声明一个变量要方便得多

  当在表上使用%ROWTYPE并将从游标中取出的值放入记录中时 如果要选择表中所有列 那么在SELECT子句中使用*比将所有列名列出来要得多

  例

  

  SET SERVERIUTPUT ON DECLARE R_emp EMP%ROWTYPE; CURSOR c_emp IS SELECT * FROM emp; BEGIN OPEN c_emp; LOOP FETCH c_emp INTO r_emp; EXIT WHEN c_emp%NOTFOUND; DBMS_OUT PUT PUT_LINE( Salary of Employee ||r_emp ename|| is || r_emp salary); END LOOP; CLOSE c_emp; END;

  %ROWTYPE也可以用游标名来定义 这样的话就必须要首先声明游标

  

  SET SERVERIUTPUT ON DECLARE CURSOR c_emp IS SELECT ename salary FROM emp; R_emp c_emp%ROWTYPE; BEGIN OPEN c_emp; LOOP FETCH c_emp INTO r_emp; EXIT WHEN c_emp%NOTFOUND; DBMS_OUT PUT PUT_LINE( Salary of Employee ||r_emp ename|| is || r_emp salary); END LOOP; CLOSE c_emp; END;

   带参数的游标

  与存储过程和函数相似 可以将参数传递给游标并在查询中使用 这对于处理在某种条件下打开游标的情况非常有用 它的语法如下

  

  CURSOR cursor_name )> IS select_statement;

  定义参数的语法如下

  

  Parameter_name data_type

  与存储过程不同的是 游标只能接受传递的值 而不能返回值 参数只定义数据类型 没有大小

  另外可以给参数设定一个缺省值 当没有参数值传递给游标时 就使用缺省值 游标中定义的参数只是一个占位符 在别处引用该参数不一定可靠

  在打开游标时给参数赋值 语法如下

  

  OPEN cursor_name >;

  参数值可以是文字或变量

  例

  

  DECALRE CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno; CURSOR c_emp (p_dept VARACHAR ) IS SELECT ename salary FROM emp WHERE deptno=p_dept ORDER BY ename r_dept DEPT%ROWTYPE; v_ename EMP ENAME%TYPE; v_salary EMP SALARY%TYPE; v_tot_salary EMP SALARY%TYPE; BEGIN OPEN c_dept; LOOP FETCH c_dept INTO r_dept; EXIT WHEN c_dept%NOTFOUND; DBMS_OUTPUT PUT_LINE ( Department: || r_dept deptno|| ||r_dept dname); v_tot_salary:= ; OPEN c_emp(r_dept deptno); LOOP FETCH c_emp INTO v_ename v_salary; EXIT WHEN c_emp%NOTFOUND; DBMS_OUTPUT PUT_LINE ( Name: || v_ename|| salary: ||v_salary); v_tot_salary:=v_tot_salary+v_salary; END LOOP; CLOSE c_emp; DBMS_OUTPUT PUT_LINE ( Toltal Salary for dept: || v_tot_salary); END LOOP; CLOSE c_dept; END;

   游标FOR循环

  在大多数时候我们在设计程序的时候都遵循下面的步骤

   打开游标

   开始循环

   从游标中取值

   那一行被返回

   处理

   关闭循环

   关闭游标

  可以简单的把这一类代码称为游标用于循环 但还有一种循环与这种类型不相同 这就是FOR循环 用于FOR循环的游标按照正常的声明方式声明 它的优点在于不需要显式的打开 关闭 取数据 测试数据的存在 定义存放数据的变量等等 游标FOR循环的语法如下

  

  FOR record_name IN (corsor_name )> | (query_difinition) LOOP statements END LOOP;

  下面我们用for循环重写上面的例子

  

  DECALRE CURSOR c_dept IS SELECT deptno dname FROM dept ORDER BY deptno; CURSOR c_emp (p_dept VARACHAR ) IS SELECT ename salary FROM emp WHERE deptno=p_dept ORDER BY ename v_tot_salary EMP SALARY%TYPE; BEGIN FOR r_dept IN c_dept LOOP DBMS_OUTPUT PUT_LINE ( Department: || r_dept deptno|| ||r_dept dname); v_tot_salary:= ; FOR r_emp IN c_emp(r_dept deptno) LOOP DBMS_OUTPUT PUT_LINE ( Name: || v_ename || salary: || v_salary); v_tot_salary:=v_tot_salary+v_salary; END LOOP; DBMS_OUTPUT PUT_LINE ( Toltal Salary for dept: || v_tot_salary); END LOOP; END;

   在游标FOR循环中使用查询

  在游标FOR循环中可以定义查询 由于没有显式声明所以游标没有名字 记录名通过游标查询来定义

  

  DECALRE v_tot_salary EMP SALARY%TYPE; BEGIN FOR r_dept IN (SELECT deptno dname FROM dept ORDER BY deptno) LOOP DBMS_OUTPUT PUT_LINE( Department: || r_dept deptno|| ||r_dept dname); v_tot_salary:= ; FOR r_emp IN (SELECT ename salary    FROM emp    WHERE deptno=p_dept    ORDER BY ename) LOOP DBMS_OUTPUT PUT_LINE( Name: || v_ename|| salary: ||v_salary); v_tot_salary:=v_tot_salary+v_salary; END LOOP; DBMS_OUTPUT PUT_LINE( Toltal Salary for dept: || v_tot_salary); END LOOP; END;

   游标中的子查询

  语法如下

  

  CURSOR C IS SELECT * FROM emp WHERE deptno NOT IN (SELECT deptno FROM dept WHERE dname!= ACCOUNTING );

  可以看出与SQL中的子查询没有什么区别

  

   游标中的更新和删除

  在PL/SQL中依然可以使用UPDATE和DELETE语句更新或删除数据行 显式游标只有在需要获得多行数据的情况下使用 PL/SQL提供了仅仅使用游标就可以执行删除或更新记录的方法

  UPDATE或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据 要使用这个方法 在声明游标时必须使用FOR UPDATE子串 当对话使用FOR UPDATE子串打开一个游标时 所有返回集中的数据行都将处于行级(ROW LEVEL)独占式锁定 其他对象只能查询这些数据行 不能进行UPDATE DELETE或SELECT FOR UPDATE操作

  语法

  

  FOR UPDATE lumnlumn>

  在多表查询中 使用OF子句来锁定特定的表 如果忽略了OF子句 那么所有表中选择的数据行都将被锁定 如果这些数据行已经被其他会话锁定 那么正常情况下ORACLE将等待 直到数据行解锁

  在UPDATE和DELETE中使用WHERE CURRENT OF子串的语法如下

  

  WHERE{CURRENT OF cursor_name|search_condition}

  例

  

  DELCARE CURSOR c IS SELECT empno salary FROM emp WHERE m IS NULL FOR UPDATE OF m; v_m NUMBER( ); BEGIN FOR r IN c LOOP IF r salary

关于关于数据库游标的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 数据库游标:使用方法及优化技巧 (关于数据库游标)