---------------------------游标:指向一个结果集的指针
--便于理解的来说:指针就可以当做是这个结果集,循环这个指针,就可以拿到该结果集里的数据、
分为:隐式游标 和 显式游标
-----------隐式游标:SELECT .... INTO ...
--需要注意:
1、查询的结果只能是1行,不能是0行或者多行
2、不需要声明,直接可以使用
-----------显示游标:
--声明显式游标的语法结构:
DECLARE
--声明的部分
CURSOR 游标名[(参数1 数据类型[,参数2 数据类型.....])]
IS
SELECT 结果集;
BEGIN
--逻辑体
END;
--开发规范:游标名以 C_ 开头
--使用/执行游标的语法结构:2种
--第1种:需要手动去打开游标,提取数据,关闭游标
DECLARE
--声明部分
BEGIN
--逻辑体
OPEN 游标名[(实际参数1[,实际参数2...])]; --打开游标
FETCH 游标名 INTO 变量; --提取数据
CLOSE 游标名; --关闭游标(千万别忘了!)
END;
--第二种:不需要手动,用FOR循环去拿到游标中的值
DECLARE
--声明部分
BEGIN
FOR 循环变量 IN 游标名 LOOP
--循环体
END LOOP;
END;
--需要注意的是:
1、显式游标需要手动声明,然后才能被使用
2、显示游标的指向的结果集可以是0行或者多行结果(包括1行)
3、使用/执行游标的方式:
1)方式1:手动管理:打开,提取,关闭
2)方式2:用for循环根据结果集的行数,依次可以拿到每一行的数据(不需要手动管理)
4、结果集时什么样子(列名,数据 等),那么在执行/使用这个游标的时候,用到的就是啥
根据列名,分别拿到每一行的结果
--比如:打印部门10的员工的工号,姓名,入职日期
DECLARE
--定义一个指针,指向部门10的员工的信息
CURSOR C_DEPT10
IS
SELECT EMPNO, ENAME, HIREDATE
FROM EMP
WHERE DEPTNO = 10;
BEGIN
--循环这个指针,分别拿到每一行的值
FOR X IN C_DEPT10 LOOP
--也就是这里的X每次可以指向这个游标(结果集)中的一行数据,从第一行开始,到最后一行结束
DBMS_OUTPUT.PUT_LINE('工号:' || X.EMPNO || ' 姓名:' || X.ENAME || ' 入职日期:' ||
TO_CHAR(X.HIREDATE, 'YYYY-MM-DD'));
END LOOP;
END;
--小练习一把:打印emp表中经理的工号,姓名,工作,工资
SELECT EMPNO,ENAME,JOB,SAL
FROM EMP
WHERE JOB = 'MANAGER';
--
DECLARE
V_JOB CONSTANT VARCHAR2(10) := 'MANAGER'; --用一个常量来接收 'MANAGER' 这个值
CURSOR C_MANAGER
IS
SELECT EMPNO, ENAME, SAL FROM EMP WHERE JOB = V_JOB;
BEGIN
FOR X IN C_MANAGER LOOP
DBMS_OUTPUT.PUT_LINE('工号:' || X.EMPNO || ' 姓名:' || X.ENAME || ' 工作:' ||
V_JOB || ' 工资:' || X.SAL);
END LOOP;
END;
---------------------带参数的游标:游标名(参数1 数据类型[,参数2 数据类型.....])
--开发规范:参数名以 P_ 开头
--比如:使用带参数的游标打印部门10和部门20的员工的工号和姓名
DECLARE
CURSOR C_DEPT(P_NO10 NUMBER, P_NO20 NUMBER)
IS
SELECT EMPNO, ENAME FROM EMP WHERE DEPTNO IN (P_NO10, P_NO20);
BEGIN
FOR X IN C_DEPT(10, 20) LOOP
DBMS_OUTPUT.PUT_LINE('工号:' || X.EMPNO || ' 姓名:' || X.ENAME);
END LOOP;
END;
--需要注意的是:
1、参数的数据类型只需要定义类型,不需要定义长度
2、参数的数据类型是什么类型,那么给具体的值就需要给对应的类型的值
3、定义了几个参数,那么使用的时候就要给几个值 (值的类型和个数 跟 定义时的 参数的类型和个数 需要一致)
--小练习一把:用带参数的游标(2个参数)打印部门30的销售的工号和姓名
DECLARE
CURSOR C_SALES(P_DEPTNO NUMBER, P_JOB VARCHAR2)
IS
SELECT EMPNO, ENAME
FROM EMP
WHERE DEPTNO = P_DEPTNO
AND JOB = P_JOB;
BEGIN
FOR X IN C_SALES(30, 'SALESMAN') LOOP
DBMS_OUTPUT.PUT_LINE('工号:' || X.EMPNO || ' 姓名:' || X.ENAME);
END LOOP;
END;
--参数的值通过变量传入
--比如:打印某个部门的经理的工号和姓名
DECLARE
V_DEPTNO NUMBER := &输入一个部门编号;
CURSOR C_MANAGER(P_DEPTNO NUMBER,P_JOB VARCHAR2)
IS
SELECT EMPNO,ENAME
FROM EMP
WHERE DEPTNO = P_DEPTNO
AND JOB = P_JOB;
BEGIN
FOR X IN C_MANAGER(V_DEPTNO, 'MANAGER') LOOP
DBMS_OUTPUT.PUT_LINE('工号:' || X.EMPNO || ' 姓名:' || X.ENAME);
END LOOP;
END;
--小练习一把:通过带参数的游标打印某个工资等级中的员工的工号和姓名以及工资等级
DECLARE
V_GRADE NUMBER(1) := &输入一个工资等级;
CURSOR C_GRADE(P_GRADE NUMBER)
IS
SELECT E.EMPNO,E.ENAME,S.GRADE
FROM EMP E JOIN SALGRADE S
ON E.SAL BETWEEN S.LOSAL AND S.HISAL
WHERE S.GRADE = P_GRADE;
BEGIN
FOR X IN C_GRADE(V_GRADE) LOOP
DBMS_OUTPUT.PUT_LINE('工号:' || X.EMPNO || ' 姓名:' || X.ENAME||' 工资等级:'||X.GRADE);
END LOOP;
END;