Oracle-PL/SQL编程语言
-
变量定义
declare 定义变量 begin 处理业务逻辑 end; -- 案例 -- 声明方法 -- 赋值操作可以使用:=也可以使用into查询语句赋值 declare -- 定义一个i 类型为number(数字或小数)长度为2 赋值为10 i number(2) := 10; -- 定义一个s 类型varchar2(字符串)长度为10 赋值为'小明' s varchar2(10) := '小明'; -- 定义一个ena 类型是emp表下的ename列的类型长度也是 ena emp.ename%type; -- 引用型变量 -- 存放emp表中的一行记录 emprow emp%rowtype; -- 记录型变量 begin -- 输出i的值 dbms_output.put_line(i); -- 输出s的值 dbms_output.put_line(s); -- 把查询出来的结果 赋值给ena (into 变量名) select ename into ena from emp where empno = 7788; -- 输出ena的值 dbms_output.put_line(ena); -- 把查询出来的结果 赋值给emprow (into 变量名) select * into emprow from emp where empno = 7788; -- 输出emprow哪一行中的数据 (|| 输出多个值得连接符) dbms_output.put_line(emprow.ename || '的工作为: ' || emprow.job); end;
-
if判断
declare 定义变量 begin if 判断 then 逻辑代码块 elsif 判断 then 逻辑代码块 else 逻辑代码块 end if; end; -- 案例 -- 输入小于18的数字, 输出未成年 -- 输入大于18小于40的数字, 输出中年人 -- 输入大于40的数字, 输出老年人 declare -- i的值是输入的 (&后面随便写个字母单词都行) i number(3) := &i; begin if i < 18 then dbms_output.put_line('未成年'); elsif i < 40 then dbms_output.put_line('中年人'); else dbms_output.put_line('老年人'); end if; end;
-
loop循环
-- while循环 declare 定义变量 begin while 判断 loop 逻辑 end loop; end; -- exit循环 declare 定义变量 begin loop exit when 判断; 逻辑 end loop; end; -- for循环 declare begin for 变量 in 范围 loop 逻辑 end loop; end; -- 案例 -- 用三种方式输出1到10的数字 -- where循环 declare i number(2) := 1; begin -- i 大于 10 时 退出循环 while i < 11 loop dbms_output.put_line(i); i := i + 1; end loop; end; -- exit循环 declare i number(2) := 1; begin loop -- i 大于 10 时 退出循环 exit when i > 10; dbms_output.put_line(i); i := i + 1; end loop; end; -- for循环 declare begin -- 循环1到10的值 for i in 1..10 loop dbms_output.put_line(i); end loop; end;
-
游标
declare cursor 游标名称 is 结果集; 定义一个记录型变量 begin open 游标名称; loop fetch 游标名称 into 记录型变量; exit when 游标名称%notfound; 业务逻辑 end loop; close 游标名称; end; -- 案例 -- 游标: 可以存放多个对象, 多行记录. -- 输出emp表中所有员工的姓名 declare -- 把emp表中的全部记录, 存储到c1游标中 cursor c1 is select * from emp; -- 定义一个记录型变量 emprow emp%rowtype; begin -- 打开游标 open c1; loop -- 把c1中遍历的每一行 都 赋值给emprow fetch c1 into emprow; -- 当它查不到的时候退出 exit when c1%notfound; -- 输出名称 dbms_output.put_line(emprow.ename); end loop; -- 关闭游标 close c1; end; -- 给指定部门员工涨工资 declare -- 定义一个带参数的游标, 参数作为条件 cursor c2(eno emp.deptno%type) is select empno from emp where deptno = eno; -- 定义一个引用型变量 en emp.empno%type; begin -- 注意:打开的时候, 必须赋值 open c2(10); loop -- 把c2中遍历的每一行 都 赋值给en fetch c2 into en; -- 当它查不到的时候退出 exit when c2%notfound; -- 执行更新语句 update emp set sal = sal + 100 where empno = en; -- 提交事务 commit; end loop; close c2; end;
-
存储过程的使用
-- 存储过程 -- 存储过程: 存储过程就是提前已经编译好的一段pl/sql语言, 放置在数据库端, -- 可以直接被调用. 这一段pl/sql一般都是固定步骤的业务. create or replace procedure 方法名(参数) is begin 业务逻辑 end; -- 案例 -- 给指定员工涨100块钱 create or replace procedure p1(eno emp.empno%type) -- 参数不写in 或者 out 默认是in is begin update emp set sal = sal + 100 where empno = eno; commit; end; -- 测试p1 declare begin -- 调用方法 传递参数 p1(7788); end;
-
存储函数
create or replace function f_yearsal(参数) return 返回值类型 is 定义变量 begin 逻辑 return 返回值; end; -- 案例 -- 通过存储函数实现计算指定员工的年薪 -- 存储过程和存储函数的参数都不能带长度 -- 存储函数的返回值类型不能带长度 create or replace function f_yearsal(eno emp.empno%type) return number is s number(10); begin select sal * 12 + nvl(comm, 0) into s from emp where empno = eno; return s; end; -- 测试f_yearsal -- 存储函数在调用的时候, 返回值需要接收. declare s number(10); begin s := f_yearsal(7788); dbms_output.put_line(s); end;
-
out类型参数的讲解
-- out类型参数如何使用 -- 使用存储过程来算年薪 create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number) is s number(10); c emp.comm%type; begin select sal * 12, nvl(comm, 0) into s, c from emp where empno = eno; yearsal := s + c; end; -- 测试p_yearsal declare yearsal number(10); begin p_yearsal(7788, yearsal); dbms_output.put_line(yearsal); end; -- in和out类型参数的区别是什么? -- 凡是涉及到into查询语句赋值或者:=赋值操作的参数, 都必须使用out来修饰.
-
存储过程和存储函数的区别
/* 存储过程和存储函数的区别 语法区别: 关键字不一样. 存储函数比存储过程多了两个return. 本质区别: 存储函数有返回值, 存储过程没有返回值. 如果存储过程想实现由返回值的业务, 我们就必须使用out类型的参数. 即便是存储过程使用了out类型的参数, 其本质也不是真的有了返回值. 而是在存储过程内部给out类型参数赋值, 在执行完毕后, 我们直接拿到输出类型参数的值. */ -- 我们可以使用存储函数有返回值的特性, 来自定义函数. -- 而存储过程不能用来自定义函数. -- 案例需求: 查询出员工姓名, 员工所在部门名称. -- 使用传统方式来实现案例需求 select e.ename, d.dname from emp e, dept d where e.deptno = d.deptno; -- 使用存储函数来实现提供一个部门编号, 输出一个部门名称. create or replace function fdna(dno dept.deptno%type) return dept.dname%type is dna dept.dname%type; begin select dept.dname into dna from dept where deptno = dno; return dna; end; -- 使用fdna存储函数来实现案例需求: 查询出员工姓名, 员工所在部门名称. select e.ename, fdna(e.deptno) from emp e;
-
触发器案例
/* 触发器, 就是制定一个规则, 在我们做增删改操作的时候, 只需要满足该规则, 自动触发, 无需调用. 语句级触发器: 不包含for each row的触发器. 行级触发器: 包含for each row的就是行级触发器. 加for each row是为了使用:old或者:new对象或者一行记录. */ -- 语句触发器 create or replace trigger 触发器名称 after -- 执行后触发 操作 on 表名称 declare begin 逻辑 end; -- 行级触发器 create or replace trigger 触发器名称 before -- 执行前触发 操作 on 表名称 for each row declare begin 逻辑 end; -- 案例 -- 语句触发器 -- 插入一条记录, 输出一个新员工入职 create or replace trigger t1 after -- 执行后触发 insert -- insert操作 on person declare begin dbms_output.put_line('一个新员工入职'); end; -- 触发t1 insert into person values(1, '小红'); commit; -- 行级触发器 -- 不能给员工降薪 -- raise_application_error(-20001~-20999之间, '错误提示信息'); create or replace trigger t2 before -- 执行前触发 update -- update操作 on emp for each row declare begin -- 修改前的工资 大于 修改后的工资 if :old.sal > :new.sal then -- 抛异常 raise_application_error(-20001, '不能给员工降薪'); end if; end; -- 触发t2 update emp set sal = sal - 1 where empno = 7788; commit;
-
使用触发器实现主键自增
-- 触发器实现主键自增. [行级触发器] -- 分析: 在用户做插入操作之前, 拿到即将插入的数据. -- 给该数据中的主键列赋值. create or replace trigger auid before insert on person for each row declare begin select s_person.nextval into :new.pid from dual; end; -- 使用auid实现主键自增 insert into person (pname) values ('小明'); commit;