内容发布更新时间 : 2024/11/18 21:47:14星期一 下面是文章的全部内容请认真阅读。
FETCH mycur INTO erow ; -- 移动游标,并将移动后的内容放到erow之中 EXIT WHEN mycur%NOTFOUND ; -- 输出之后还需要继续移动游标 DBMS_OUTPUT.PUT_LINE(erow.empno || ' --> ' || erow.ename) ; END LOOP ; CLOSE mycur ; -- 关闭游标 END ; / 此时,结果同样出来了,但是使用以上的循环操作最麻烦的地方在于需要手工打开游标并且手工关闭游标,手工移动游标,那么在Oracle中为了简
化这种操作,对于for循环提供新的支持。
DECLARE erow emp%ROWTYPE ; -- 此变量可以装下一行的emp记录 BEGIN FOR erow IN mycur LOOP -- 自动打开、关闭、移动游标 DBMS_OUTPUT.PUT_LINE(erow.empno || ' --> ' || erow.ename) ; END LOOP ; END ; / 实际上,所谓的游标就是可以将数据一条条的进行处理操作。
练习:
一次性上涨所有雇员的工资,增长工资按照以下的原则进行:
· 10部门人员工资上涨10% · 20部门人员工资上涨20% · 30部门人员工资上涨30%
CURSOR mycur IS SELECT * FROM emp ; -- 声明一个游标,游标的名称是mycur DECLARE erow emp%ROWTYPE ; -- 此变量可以装下一行的emp记录 BEGIN FOR erow IN mycur LOOP -- 自动打开、关闭、移动游标 IF erow.deptno=10 THEN IF erow.sal*1.1>5000 THEN UPDATE emp SET sal=5000 WHERE empno=erow.empno ; ELSE UPDATE emp SET sal=sal*1.1 WHERE empno=erow.empno ; END IF ; ELSIF erow.deptno=20 THEN IF erow.sal>5000 THEN UPDATE emp SET sal=5000 WHERE empno=erow.empno ; ELSE UPDATE emp SET sal=sal*1.2 WHERE empno=erow.empno ; END IF ; ELSIF erow.deptno=30 THEN IF erow.sal>5000 THEN UPDATE emp SET sal=5000 WHERE empno=erow.empno ; CURSOR mycur IS SELECT * FROM emp ; -- 声明一个游标,游标的名称是mycur ELSE UPDATE emp SET sal=sal*1.3 WHERE empno=erow.empno ; END IF ; ELSE null; -- 如果都不满足,则什么也不操作 END IF ; END LOOP ; END ; / 对于此种复杂的方式只能通过游标进行依次的操作。
游标可以增加参数,这种游标称为参数游标,例如:要求输入一个部门编号,查询出部门的雇员信息。
DECLARE erow emp%ROWTYPE ; -- 此变量可以装下一行的emp记录 -- 声明一个CURSOR mycur(dno emp.deptno%TYPE) IS SELECT * FROM emp WHERE deptno=dno ; 游标,游标的名称是mycur BEGIN FOR erow IN mycur(&deptnumber) LOOP -- 自动打开、关闭、移动游标 DBMS_OUTPUT.PUT_LINE(erow.empno || ' --> ' || erow.ename) ; END LOOP ; END ; / 之前可以发现在游标中可以使用%FOUND、%NOTFOUND、%ROWCOUNT、%ISOPEN。
DECLARE erow emp%ROWTYPE ; -- 此变量可以装下一行的emp记录 BEGIN FOR erow IN mycur LOOP -- 自动打开、关闭、移动游标 DBMS_OUTPUT.PUT_LINE(mycur%ROWCOUNT || '、' ||erow.empno || ' --> ' || erow.ename) ; END LOOP ; END ; / 可以发现ROWCOUNT与ROWNUM功能是一样的,可以通过此功能求出行号。
CURSOR mycur IS SELECT * FROM emp ; -- 声明一个游标,游标的名称是mycur 3.3、过程
过程 = 过程的声明 + PLSQL块
范例:创建一个过程
CREATE OR REPLACE PROCEDURE myproc AS BEGIN null ; END ; / 范例:定义一个完整的过程,可以接收参数,并且根据雇员的编号找出其工资
CREATE OR REPLACE PROCEDURE myproc(eno emp.empno%TYPE) AS esal emp.sal%TYPE ; BEGIN SELECT sal INTO esal FROM emp WHERE empno=eno ; DBMS_OUTPUT.PUT_LINE('工资是:' || esal) ; END ; / 此时,过程已经成功的创建了。
过程是需要调用的,使用exec 过程(参数)的形式调用。exec myproc(7369)
此时,一个过程已经正常的执行完毕。
范例:定义一个过程,通过此过程可以自动加入部门信息
CREATE OR REPLACE PROCEDURE myproc(dno dept.deptno%TYPE,name dept.dname%TYPE,lo dept.loc%TYPE) AS BEGIN INSERT INTO dept(deptno,dname,loc) VALUES (dno,name,lo) ; END ; / exec myproc(50,'技术部','北京') ;
范例:但是进一步思考的话,会发现,部门的编号不应该存在重复,如果重复的话不应该执行插入
CREATE OR REPLACE PROCEDURE myproc(dno dept.deptno%TYPE,name dept.dname%TYPE,lo dept.loc%TYPE) AS coun NUMBER ; BEGIN SELECT COUNT(deptno) INTO coun FROM dept WHERE deptno=dno ; IF coun>0 THEN DBMS_OUTPUT.PUT_LINE('此部门信息已经存在!') ; ELSE INSERT INTO dept(deptno,dname,loc) VALUES (dno,name,lo) ; END IF ; END ; / exec myproc(50,'技术部','北京') ; 实际上对于过程的参数也有三种类型: · IN(传递一个数值,默认的)
· IN OUT(带值进,并且修改后的值可以带出来)
· OUT(不带值进,但是可以带值出)
范例:定义参数过程
CREATE OR REPLACE PROCEDURE myproc(eno IN emp.empno%TYPE,esal OUT emp.sal%TYPE) AS BEGIN SELECT sal INTO esal FROM emp WHERE empno=eno ; END ; / 调用过程,并且观察变量的内容,为了更好的观察,定义若干个变量
DECLARE eno emp.empno%TYPE ; esalary emp.sal%TYPE ; BEGIN eno := &empno ; myproc(eno,esalary) ; DBMS_OUTPUT.put_LINE(esalary) ; END ; / 可以发现,过程直接通过PLSQL块调用。
3.4、函数
之前曾经使用过很多的函数:LOWER、UPPER,那么在数据库之中也可以自己定义函数。
范例:定义一个函数
CREATE OR REPLACE FUNCTION myfun(eno NUMBER) RETURN NUMBER AS esal NUMBER ; BEGIN SELECT sal + NVL(comm,0) INTO esal FROM emp WHERE empno=eno ; RETURN esal ; -- 把内容返回 END ; / 下面就按照之前调用普通函数那样,直接使用即可。
SELECT myfun(7369) FROM dual ;