-- 声明游标;CURSOR cursor_name IS select_statement
--For 循环游标
--(1)定义游标
--(2)定义游标变量
--(3)使用for循环来使用这个游标
DECLARE
--类型定义
CURSOR C_JOB IS
SELECT EMPNO, ENAME, JOB, SAL FROM EMP WHERE JOB = 'MANAGER';
--定义一个游标变量v_cinfo c_emp%ROWTYPE ,该类型为游标c_emp中的一行数据类型
C_ROW C_JOB%ROWTYPE;
BEGIN
FOR C_ROW IN C_JOB LOOP
DBMS_OUTPUT.PUT_LINE(C_ROW.EMPNO || '-' || C_ROW.ENAME || '-' ||
C_ROW.JOB || '-' || C_ROW.SAL);
END LOOP;
END;
--Fetch游标
--使用的时候必须要明确的打开和关闭
DECLARE
--类型定义
CURSOR C_JOB IS
SELECT EMPNO, ENAME, JOB, SAL FROM EMP WHERE JOB = 'MANAGER';
--定义一个游标变量
C_ROW C_JOB%ROWTYPE;
BEGIN
OPEN C_JOB;
LOOP
--提取一行数据到c_row
FETCH C_JOB
INTO C_ROW;
--判读是否提取到值,没取到值就退出
--取到值c_job%notfound 是false
--取不到值c_job%notfound 是true
EXIT WHEN C_JOB%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(C_ROW.EMPNO || '-' || C_ROW.ENAME || '-' ||
C_ROW.JOB || '-' || C_ROW.SAL);
END LOOP;
--关闭游标
CLOSE C_JOB;
END;
--1:任意执行一个update操作,用隐式游标sql的属性%found,%notfound,%rowcount,%isopen观察update语句的执行情况。
BEGIN
UPDATE EMP SET ENAME = 'ALEARK' WHERE EMPNO = 7469;
IF SQL%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Openging');
ELSE
DBMS_OUTPUT.PUT_LINE('closing');
END IF;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('游标指向了有效行'); --判断游标是否指向有效行
ELSE
DBMS_OUTPUT.PUT_LINE('Sorry');
END IF;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('Also Sorry');
ELSE
DBMS_OUTPUT.PUT_LINE('Haha');
END IF;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Sorry No data');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('Too Many rows');
END;
DECLARE
EMPNUMBER EMP.EMPNO%TYPE;
EMPNAME EMP.ENAME%TYPE;
BEGIN
IF SQL%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor is opinging');
ELSE
DBMS_OUTPUT.PUT_LINE('Cursor is Close');
END IF;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('No Value');
ELSE
DBMS_OUTPUT.PUT_LINE(EMPNUMBER);
END IF;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
DBMS_OUTPUT.PUT_LINE('-------------');
SELECT EMPNO, ENAME INTO EMPNUMBER, EMPNAME FROM EMP WHERE EMPNO = 7499;
DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT);
IF SQL%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor is opinging');
ELSE
DBMS_OUTPUT.PUT_LINE('Cursor is Closing');
END IF;
IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('No Value');
ELSE
DBMS_OUTPUT.PUT_LINE(EMPNUMBER);
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No Value');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('too many rows');
END;
--2,使用游标和loop循环来显示所有部门的名称
--游标声明
DECLARE
CURSOR CSR_DEPT IS
--select语句
SELECT DNAME FROM DEPTH;
--指定行指针,这句话应该是指定和csr_dept行类型相同的变量
ROW_DEPT CSR_DEPT%ROWTYPE;
BEGIN
--for循环
FOR ROW_DEPT IN CSR_DEPT LOOP
DBMS_OUTPUT.PUT_LINE('部门名称:' || ROW_DEPT.DNAME);
END LOOP;
END;
--3,使用游标和while循环来显示所有部门的的地理位置(用%found属性)
DECLARE
--游标声明
CURSOR CSR_TESTWHILE IS
--select语句
SELECT LOC FROM DEPTH;
--指定行指针
ROW_LOC CSR_TESTWHILE%ROWTYPE;
BEGIN
--打开游标
OPEN CSR_TESTWHILE;
--给第一行喂数据
FETCH CSR_TESTWHILE
INTO ROW_LOC;
--测试是否有数据,并执行循环
WHILE CSR_TESTWHILE%FOUND LOOP
DBMS_OUTPUT.PUT_LINE('部门地点:' || ROW_LOC.LOC);
--给下一行喂数据
FETCH CSR_TESTWHILE
INTO ROW_LOC;
END LOOP;
CLOSE CSR_TESTWHILE;
END;
SELECT *
FROM EMP
--4,接收用户输入的部门编号,用for循环和游标,打印出此部门的所有雇员的所有信息(使用循环游标)
--CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;
--定义参数的语法如下:Parameter_name [IN] data_type[{:=|DEFAULT} value]
DECLARE CURSOR C_DEPT(P_DEPTNO NUMBER) IS
SELECT * FROM EMP WHERE EMP.DEPNO = P_DEPTNO;
R_EMP EMP%ROWTYPE;
BEGIN
FOR R_EMP IN C_DEPT(20) LOOP
DBMS_OUTPUT.PUT_LINE('员工号:' || R_EMP.EMPNO || '员工名:' || R_EMP.ENAME ||
'工资:' || R_EMP.SAL);
END LOOP;
END;
SELECT *
FROM EMP
--5:向游标传递一个工种,显示此工种的所有雇员的所有信息(使用参数游标)
DECLARE CURSOR C_JOB(P_JOB NVARCHAR2) IS
SELECT * FROM EMP WHERE JOB = P_JOB;
R_JOB EMP%ROWTYPE;
BEGIN
FOR R_JOB IN C_JOB('CLERK') LOOP
DBMS_OUTPUT.PUT_LINE('员工号' || R_JOB.EMPNO || ' ' || '员工姓名' ||
R_JOB.ENAME);
END LOOP;
END;
SELECT *
FROM EMP
--6:用更新游标来为雇员加佣金:(用if实现,创建一个与emp表一摸一样的emp1表,对emp1表进行修改操作),并将更新前后的数据输出出来
--http://zheng12tian.iteye.com/blog/815770
CREATE TABLE EMP1 AS
SELECT * FROM EMP;
DECLARE
CURSOR CSR_UPDATE IS
SELECT * FROM EMP1 FOR UPDATE OF SAL;
EMPINFO CSR_UPDATE%ROWTYPE;
SALEINFO EMP1.SAL%TYPE;
BEGIN
FOR EMPINFO IN CSR_UPDATE LOOP
IF EMPINFO.SAL < 1500 THEN
SALEINFO := EMPINFO.SAL * 1.2;
ELSIF EMPINFO.SAL < 2000 THEN
SALEINFO := EMPINFO.SAL * 1.5;
ELSIF EMPINFO.SAL < 3000 THEN
SALEINFO := EMPINFO.SAL * 2;
END IF;
UPDATE EMP1 SET SAL = SALEINFO WHERE CURRENT OF CSR_UPDATE;
END LOOP;
END;
--7:编写一个PL/SQL程序块,对名字以‘A’或‘S’开始的所有雇员按他们的基本薪水(sal)的10%给他们加薪(对emp1表进行修改操作)
DECLARE
CURSOR CSR_ADDSAL IS
SELECT *
FROM EMP1
WHERE ENAME LIKE 'A%'
OR ENAME LIKE 'S%'
FOR UPDATE OF SAL;
R_ADDSAL CSR_ADDSAL%ROWTYPE;
SALEINFO EMP1.SAL%TYPE;
BEGIN
FOR R_ADDSAL IN CSR_ADDSAL LOOP
DBMS_OUTPUT.PUT_LINE(R_ADDSAL.ENAME || '原来的工资:' || R_ADDSAL.SAL);
SALEINFO := R_ADDSAL.SAL * 1.1;
UPDATE EMP1 SET SAL = SALEINFO WHERE CURRENT OF CSR_ADDSAL;
END LOOP;
END;
--8:编写一个PL/SQL程序块,对所有的salesman增加佣金(comm)500
DECLARE
CURSOR CSR_ADDCOMM(P_JOB NVARCHAR2) IS
SELECT * FROM EMP1 WHERE JOB = P_JOB FOR UPDATE OF COMM;
R_ADDCOMM EMP1%ROWTYPE;
COMMINFO EMP1.COMM%TYPE;
BEGIN
FOR R_ADDCOMM IN CSR_ADDCOMM('SALESMAN') LOOP
COMMINFO := R_ADDCOMM.COMM + 500;
UPDATE EMP1 SET COMM = COMMINFO WHERE CURRENT OF CSR_ADDCOMM;
END LOOP;
END;
--9:编写一个PL/SQL程序块,以提升2个资格最老的职员为MANAGER(工作时间越长,资格越老)
--(提示:可以定义一个变量作为计数器控制游标只提取两条数据;也可以在声明游标的时候把雇员中资格最老的两个人查出来放到游标中。)
DECLARE
CURSOR CRS_TESTCOMPUT IS
SELECT * FROM EMP1 ORDER BY HIREDATE ASC;
--计数器
TOP_TWO NUMBER := 2;
R_TESTCOMPUT CRS_TESTCOMPUT%ROWTYPE;
BEGIN
OPEN CRS_TESTCOMPUT;
FETCH CRS_TESTCOMPUT
INTO R_TESTCOMPUT;
WHILE TOP_TWO > 0 LOOP
DBMS_OUTPUT.PUT_LINE('员工姓名:' || R_TESTCOMPUT.ENAME || ' 工作时间:' ||
R_TESTCOMPUT.HIREDATE);
--计速器减一
TOP_TWO := TOP_TWO - 1;
FETCH CRS_TESTCOMPUT
INTO R_TESTCOMPUT;
END LOOP;
CLOSE CRS_TESTCOMPUT;
END;
--10:编写一个PL/SQL程序块,对所有雇员按他们的基本薪水(sal)的20%为他们加薪,
--如果增加的薪水大于300就取消加薪(对emp1表进行修改操作,并将更新前后的数据输出出来)
DECLARE
CURSOR CRS_UPADATESAL IS
SELECT * FROM EMP1 FOR UPDATE OF SAL;
R_UPDATESAL CRS_UPADATESAL%ROWTYPE;
SALADD EMP1.SAL%TYPE;
SALINFO EMP1.SAL%TYPE;
BEGIN
FOR R_UPDATESAL IN CRS_UPADATESAL LOOP
SALADD := R_UPDATESAL.SAL * 0.2;
IF SALADD > 300 THEN
SALINFO := R_UPDATESAL.SAL;
DBMS_OUTPUT.PUT_LINE(R_UPDATESAL.ENAME || ': 加薪失败。' || '薪水维持在:' ||
R_UPDATESAL.SAL);
ELSE
SALINFO := R_UPDATESAL.SAL + SALADD;
DBMS_OUTPUT.PUT_LINE(R_UPDATESAL.ENAME || ': 加薪成功.' || '薪水变为:' ||
SALINFO);
END IF;
UPDATE EMP1 SET SAL = SALINFO WHERE CURRENT OF CRS_UPADATESAL;
END LOOP;
END;
--11:将每位员工工作了多少年零多少月零多少天输出出来
--近似
--CEIL(n)函数:取大于等于数值n的最小整数
--FLOOR(n)函数:取小于等于数值n的最大整数
--truc的用法 http://publish.it168.com/2005/1028/20051028034101.shtml
DECLARE
CURSOR CRS_WORKDAY IS
SELECT ENAME,
HIREDATE,
TRUNC(MONTHS_BETWEEN(SYSDATE, HIREDATE) / 12) AS SPANDYEARS,
TRUNC(MOD(MONTHS_BETWEEN(SYSDATE, HIREDATE), 12)) AS MONTHS,
TRUNC(MOD(MOD(SYSDATE - HIREDATE, 365), 12)) AS DAYS
FROM EMP1;
R_WORKDAY CRS_WORKDAY%ROWTYPE;
BEGIN
FOR R_WORKDAY IN CRS_WORKDAY LOOP
DBMS_OUTPUT.PUT_LINE(R_WORKDAY.ENAME || '已经工作了' ||
R_WORKDAY.SPANDYEARS || '年,零' || R_WORKDAY.MONTHS ||
'月,零' || R_WORKDAY.DAYS || '天');
END LOOP;
END;
--12:输入部门编号,按照下列加薪比例执行(用CASE实现,创建一个emp1表,修改emp1表的数据),并将更新前后的数据输出出来
-- deptno raise(%)
-- 10 5%
-- 20 10%
-- 30 15%
-- 40 20%
-- 加薪比例以现有的sal为标准
--CASE expr WHEN comparison_expr THEN return_expr
--[, WHEN comparison_expr THEN return_expr]... [ELSE else_expr] END
DECLARE
CURSOR CRS_CASETEST IS
SELECT * FROM EMP1 FOR UPDATE OF SAL;
R_CASETEST CRS_CASETEST%ROWTYPE;
SALINFO EMP1.SAL%TYPE;
BEGIN
FOR R_CASETEST IN CRS_CASETEST LOOP
CASE
WHEN R_CASETEST.DEPNO = 10 THEN
SALINFO := R_CASETEST.SAL * 1.05;
WHEN R_CASETEST.DEPNO = 20 THEN
SALINFO := R_CASETEST.SAL * 1.1;
WHEN R_CASETEST.DEPNO = 30 THEN
SALINFO := R_CASETEST.SAL * 1.15;
WHEN R_CASETEST.DEPNO = 40 THEN
SALINFO := R_CASETEST.SAL * 1.2;
END CASE;
UPDATE EMP1 SET SAL = SALINFO WHERE CURRENT OF CRS_CASETEST;
END LOOP;
END;
--13:对每位员工的薪水进行判断,如果该员工薪水高于其所在部门的平均薪水,则将其薪水减50元,输出更新前后的薪水,员工姓名,所在部门编号。
--AVG([distinct|all] expr) over (analytic_clause)
---作用:
--按照analytic_clause中的规则求分组平均值。
--分析函数语法:
--FUNCTION_NAME(<argument>,<argument>...)
--OVER
--(<Partition-Clause><Order-by-Clause><Windowing Clause>)
--PARTITION子句
--按照表达式分区(就是分组),如果省略了分区子句,则全部的结果集被看作是一个单一的组
SELECT *
FROM EMP1 DECLARE CURSOR CRS_TESTAVG IS
SELECT EMPNO,
ENAME,
JOB,
SAL,
DEPNO,
AVG(SAL) OVER(PARTITION BY DEPNO) AS DEP_AVG
FROM EMP1
FOR UPDATE OF SAL;
R_TESTAVG CRS_TESTAVG%ROWTYPE;
SALINFO EMP1.SAL%TYPE;
BEGIN
FOR R_TESTAVG IN CRS_TESTAVG LOOP
IF R_TESTAVG.SAL > R_TESTAVG.DEP_AVG THEN
SALINFO := R_TESTAVG.SAL - 50;
END IF;
UPDATE EMP1 SET SAL = SALINFO WHERE CURRENT OF CRS_TESTAVG;
END LOOP;
END;
分享到:
相关推荐
Oracle 游标使用方法及语法大全 Oracle 游标是 PL/SQL 程序中的一种重要组件,用于处理查询结果集。游标可以分为隐式游标和显式游标两种,隐式游标由 PL/SQL 管理,隐式游标打开时查询开始,查询结束时隐式游标自动...
### Oracle游标使用详解 #### 一、游标概述 游标是Oracle数据库中用于处理查询结果集的强大工具,尤其适用于需要逐行处理查询结果的情况。在Oracle中,游标可以分为两类:**显式游标**和**隐式游标**。 1. **隐式...
根据提供的标题、描述以及部分代码内容,我们可以详细探讨Oracle游标的使用方法,特别是明确游标(Explicit Cursor)和隐式游标(Implicit Cursor)的区别及其具体应用方式。 ### Oracle游标简介 在Oracle数据库中...
本资源“Oracle游标使用案例大全”提供了一系列实用的示例,旨在帮助学习者深入理解和掌握Oracle游标的用法。 1. **游标的基本概念** - 游标(Cursor):它是一个数据库系统中的结构,用于存储执行SQL查询后的结果...
通过本篇Oracle游标的使用大全,我们可以了解到Oracle数据库游标的类型、属性以及如何在PL/SQL中实现对数据集的逐行处理。这不仅有助于提升程序员的编程技能,也能使他们更深入地理解PL/SQL与Oracle数据库之间的交互...
这篇文档《Oracle 游标使用大全》应该涵盖了关于Oracle游标的各种使用方法和最佳实践。 1. **游标的定义与类型** - 游标(Cursor)是数据库系统中一个概念,用于跟踪查询结果集中的当前位置。 - Oracle游标有两种...
Oracle游标是数据库编程中非常重要的一个概念,主要用于处理SQL查询返回的多行结果集。在PL/SQL中,游标分为隐式游标和显式游标。 1. **隐式游标**:在PL/SQL中,每当执行一个SELECT语句时,系统会自动打开一个隐式...
本文详细介绍了Oracle游标的使用方法,包括如何声明、打开游标,如何使用变量与类型匹配,以及如何处理异常情况等。通过这些知识点的学习,读者可以更好地理解和应用Oracle游标,提高开发效率和代码质量。此外,还...
总之,Oracle游标提供了处理查询结果的强大工具,使开发者能够灵活地在PL/SQL中操作数据。无论是隐式还是显式游标,都极大地增强了对数据库的交互能力,使得程序能根据查询结果进行适当的操作。理解并熟练运用游标是...
PL/SQL 提供了仅仅使用游标就可以执行删除或更新记录的方法。 游标 FOR 循环的示例 下面是一个使用游标 FOR 循环的示例代码: ``` DECLARE CURSOR c_dept IS SELECT deptno, dname FROM dept ORDER BY deptno; ...
3. **游标的使用方法**: - **声明游标**:使用`DECLARE`关键字定义游标,指定查询语句和返回的数据类型。 - **打开游标**:使用`OPEN`语句打开游标,准备进行`FETCH`操作。 - **提取数据**:使用`FETCH`语句从...
### Oracle游标优化 ...通过上述方法,可以在一定程度上优化Oracle游标的性能,从而提高应用程序的整体响应时间和资源利用率。需要注意的是,每种优化策略都应该根据具体的业务需求和技术环境来选择和实施。
oracle游标的用法,比较通俗易懂的讲解游标用法,有实例
### Oracle游标详解 在Oracle数据库中,游标(Cursor)是处理数据集的一个关键机制,主要用于执行查询并逐行处理结果集。游标可以被视为一个临时存储区,用于保存SELECT语句的结果集,允许程序对这些结果进行迭代...
根据提供的文件信息,我们可以归纳出以下Oracle游标的使用方法及相关知识点: ### 一、游标的基本概念 在Oracle数据库中,游标是一种重要的机制,它允许用户从查询结果集中逐行检索数据。游标可以分为两种类型:**...
【Oracle游标的使用方法】 Oracle游标是数据库管理系统中用于处理SQL语句的重要工具,它允许程序逐行处理查询结果,而不是一次性加载所有数据。游标由上下文区支持,这是一个内存区域,存储了处理SQL语句所需的信息...
在这个主题中,我们将深入探讨游标的定义、类型、使用方法以及在实际应用中的重要性。 游标(Cursor)在数据库中扮演着数据指针的角色,它允许我们在结果集中移动,读取单个记录或更新特定行。Oracle提供两种类型的...
【Oracle游标学习】 在Oracle数据库中,游标(Cursor)是一种重要的编程工具,它允许开发者按需处理查询结果集的每一行数据。游标在PL/SQL编程中扮演着关键角色,尤其在处理大量数据时,能提供更加灵活和高效的数据...