oracle第三天
Posted zhaoshuzhan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle第三天相关的知识,希望对你有一定的参考价值。
HelloWorld.sql
set serveroutput on
declare
--说明部分
begin
--程序
dbms_output.put_line(‘Hello World‘);
end;
/
if语句.sql
--判断用户输入的数字
set serveroutput on
--接收键盘输入
--num: 地址值,在该地址上,存了输入的值
accept num prompt ‘请输入一个数字‘;
declare
--定义变量保存输入的数字
--隐式转换
pnum number := #
begin
if pnum = 0 then dbms_output.put_line(‘您输入的是0‘);
elsif pnum = 1 then dbms_output.put_line(‘您输入的是1‘);
elsif pnum = 2 then dbms_output.put_line(‘您输入的是2‘);
else dbms_output.put_line(‘其他数字‘);
end if;
end;
/
带参数的光标.sql
--查询某个部门中员工的姓名
set serveroutput on
declare
--带参数的光标
cursor cemp(dno number) is select ename from emp where deptno=dno;
pename emp.ename%type;
begin
open cemp(20);
loop
fetch cemp into pename;
exit when cemp%notfound;
dbms_output.put_line(pename);
end loop;
close cemp;
end;
/
给员工涨工资.sql
--涨工资 总裁1000 经理800 其他400
set serveroutput on
declare
cursor cemp is select empno,empjob from emp;
pempno emp.empno%type;
pjob emp.empjob%type;
begin
rollback;
open cemp;
loop
--取一个员工 涨工资
fetch cemp into pempno,pjob;
exit when cemp%notfound;
--判断职位
if pjob = ‘PRESIDENT‘ then update emp set sal=sal+1000 where empno=pempno;
elsif pjob = ‘MANAGER‘ then update emp set sal=sal+800 where empno=pempno;
else update emp set sal=sal+400 where empno=pempno;
end if;
end loop;
close cemp;
--事务的隔离级别
commit;
dbms_output.put_line(‘涨工资完成‘);
end;
/
光标
--使用游标查询员工姓名和工资,并打印
/*
1. 光标的属性
%isopen: 是否打开
%rowcount: 行数
%notfound: 没有记录
2. 默认允许一次打开300个光标(修改光标: 第四天 管理方案)
SQL> show parameters cursor
NAME TYPE VALUE
------------------------------------ ----------- -------
cursor_sharing string EXACT
cursor_space_for_time boolean FALSE
open_cursors integer 300
session_cached_cursors integer 20
*/
set serveroutput on
declare
--定义光标代表员工集合
cursor cemp is select ename,sal from emp;
pename emp.ename%type;
psal emp.sal%type;
begin
open cemp;
loop
--取一个员工
fetch cemp into pename,psal;
--退出条件
exit when cemp%notfound;
dbms_output.put_line(pename||‘的薪水是‘||psal);
end loop;
close cemp;
end;
/
记录型变量
----查询并打印7839的姓名和薪水
set serveroutput on
declare
--记录型变量 代表一行
emp_rec emp%rowtype;
begin
select * into emp_rec from emp where empno=7839;
dbms_output.put_line(emp_rec.ename||‘的薪水是‘||emp_rec.sal);
end;
/
实例1
/*
实例1:统计每年入职的员工个数。
SQL语句
1. select to_char(hiredate,‘RR‘) from emp; --> 光标 --> 循环(notfound)
2. count80 number := 0;
count81 number := 0;
count82 number := 0;
count87 number := 0;
*/
set serveroutput on
declare
cursor cemp is select to_char(hiredate,‘RR‘) from emp;
phiredate varchar2(4);
--计数器
count80 number := 0;
count81 number := 0;
count82 number := 0;
count87 number := 0;
begin
open cemp;
loop
--取一个员工
fetch cemp into phiredate;
exit when cemp%notfound;
--判断年份
if phiredate = ‘80‘ then count80:=count80+1;
elsif phiredate = ‘81‘ then count81:=count81+1;
elsif phiredate = ‘82‘ then count82:=count82+1;
else count87:=count87+1;
end if;
end loop;
close cemp;
dbms_output.put_line(‘Total:‘||(count80+count81+count82+count87));
dbms_output.put_line(‘80:‘||count80);
dbms_output.put_line(‘81:‘||count81);
dbms_output.put_line(‘82:‘||count82);
dbms_output.put_line(‘87:‘||count87);
end;
/
实例2
/*
为员工长工资。从最低工资调起每人长10%,但工资总额不能超过5万元,
请计算长工资的人数和长工资后的工资总额,并输出输出长工资人数及工资总额。
SQL语句:
1. select empno,sal from emp order by sal;-->光标 -->循环(1. > 5w 2. 涨完)
2. countEmp number := 0;
3. 长工资后的工资总额: *. select sum(sal) from emp
*. 涨后=涨前+sal*0.1 (*)
练习: 工资<5w
*/
set serveroutput on
declare
cursor cemp is select empno,sal from emp order by sal;
pempno emp.empno%type;
psal emp.sal%type;
--人数
countEmp number := 0;
--工资总额
salTotal number;
begin
--初始的工资总额
select sum(sal) into salTotal from emp;
open cemp;
loop
--第一个退出条件
exit when salTotal> 50000;
--取一个员工
fetch cemp into pempno,psal;
--第二个退出条件
exit when cemp%notfound;
--涨工资
update emp set sal =sal *1.1 where empno=pempno;
--人数
countEmp := countEmp+1;
--工资总额
salTotal := salTotal + psal *0.1;
end loop;
close cemp;
commit;
dbms_output.put_line(‘人数:‘||countEmp||‘ 工资总额:‘||salTotal);
end;
/
实例3
/*
用PL/SQL语言编写一程序,实现按部门分段(6000以上、(6000,3000)、3000元以下)
统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)
SQL语句
1. 部门: select deptno from dept; --> 光标 --> 循环
2. 部门中员工的薪水: select sal from emp where deptno=??? --> 带参数的光标 --> 循环
3. count1 number; count2 number; count3 number;
4. 部门工资总额: salTotal number;
select sum(sal) into salTotal from emp where deptno=???
*/
set serveroutput on
declare
--部门
cursor cdept is select deptno from dept;
pdeptno dept.deptno%type;
--部门中员工的薪水
cursor cemp(dno number) is select sal from emp where deptno=dno;
psal emp.sal%type;
--计数器
count1 number; count2 number; count3 number;
--部门的工资总额
salTotal number;
begin
open cdept;
loop
--取一个部门
fetch cdept into pdeptno;
exit when cdept%notfound;
--初始化
count1:=0;count2:=0;count3:=0;
--部门的工资总额
select sum(sal) into salTotal from emp where deptno=pdeptno;
--部门中员工的薪水
open cemp(pdeptno);
loop
--取一个员工的薪水cl
fetch cemp into psal;
exit when cemp%notfound;
--判断
if psal< 3000 then count1:=count1+1;
elsif psal>=3000 and psal<6000 then count2:=count2+1;
else count3:=count3+1;
end if;
end loop;
close cemp;
-- 保存当前结果
insert into msg1 values(pdeptno,count1,count2,count3,nvl(salTotal,0));
end loop;
close cdept;
commit;
dbms_output.put_line(‘完成‘);
end;
/
系统例外
--被0除
set serveroutput on
declare
pnum number;
begin
pnum := 1/0;
exception
when Zero_Divide then dbms_output.put_line(‘1:0不能做被除数‘);
dbms_output.put_line(‘2:0不能做被除数‘);
when Value_error then dbms_output.put_line(‘算术或转换错误‘);
when others then dbms_output.put_line(‘其他例外‘);
end;
/
--打印1~10
set serveroutput on
declare
pnum number := 1;
begin
loop
--退出循环
exit when pnum > 10;
dbms_output.put_line(pnum);
--加一
pnum := pnum + 1;
end loop;
end;
/
引用型变量
--查询并打印7839的姓名和薪水
set serveroutput on
declare
--定义引用型变量
pename emp.ename%type;
psal emp.sal%type;
begin
--查询7839的姓名和薪水
select ename,sal into pename,psal from emp where empno=7839;
-- 打印
dbms_output.put_line(pename||‘的薪水是‘||psal);
end;
/
自定义例外
--查询50号部门的员工
set serveroutput on
declare
cursor cemp is select ename from emp where deptno=50;
pename emp.ename%type;
--自定义例外
no_emp_found exception;
begin
open cemp;
--取一个员工
fetch cemp into pename;
if cemp%notfound then
--抛出例外
raise no_emp_found;
end if;
--当抛出例外,自动关闭
close cemp;
exception
when no_emp_found then dbms_output.put_line(‘没有找到员工‘);
when others then dbms_output.put_line(‘其他例外‘);
end;
/
out参数
/*
create [or replace] PROCEDURE 过程名(参数列表)
AS
PLSQL子程序体;
查询并返回某个员工的姓名 月薪和职位
思考: out参数太多???
*/
create or replace procedure queryEmpInfo(eno in number,
pename out varchar2,
psal out number,
pjob out varchar2)
as
begin
select ename,sal,empjob into pename,psal,pjob from emp where empno=eno;
end;
/
触发器应用场景二
/*
数据确认
涨后的薪水不能少于涨前的薪水
CREATE [or REPLACE] TRIGGER 触发器名
{BEFORE | AFTER}
{DELETE | INSERT | UPDATE [OF 列名]}
ON 表名
[FOR EACH ROW [WHEN(条件) ] ]
PLSQL 块
*/
create or replace trigger checksal
before update
on emp
for each row
begin
--if 涨后的薪水< 涨前的薪水 then
if :new.sal < :old.sal then
raise_application_error(-20002,‘涨后的薪水不能少于涨前的薪水.涨前:‘||:old.sal||‘ 涨后:‘||:new.sal);
end if;
end;
/
触发器应用场景一
/*
实施复杂的安全性检查
禁止在非工作时间 往emp表中插入数据
CREATE [or REPLACE] TRIGGER 触发器名
{BEFORE | AFTER}
{DELETE | INSERT | UPDATE [OF 列名]}
ON 表名
PLSQL 块
周末:to_char(sysdate,‘day‘) in (‘星期六‘,‘星期日‘)
上班前 下班后: to_number(to_char(sysdate,‘hh24‘)) not between 9 and 18
*/
create or replace trigger securityEmp
before insert
on emp
begin
if to_char(sysdate,‘day‘) in (‘星期六‘,‘星期日‘) or
to_number(to_char(sysdate,‘hh24‘)) not between 9 and 18 then
raise_application_error(-20001,‘不能在非工作时间插入数据‘);
end if;
end;
/
存储函数
/*
CREATE [OR REPLACE] FUNCTION 函数名(参数列表)
RETURN 函数值类型
AS
PLSQL子程序体;
查询某个员工的年收入
*/
create or replace function queryEmpIncome(eno in number)
return number
as
psal emp.sal%type;
pcomm emp.comm%type;
begin
select sal,comm into psal,pcomm from emp where empno=eno;
return psal*12+nvl(pcomm,0);
end;
/
带参数的存储过程
/*
create [or replace] PROCEDURE 过程名(参数列表)
AS
PLSQL子程序体;
为指定的员工涨100块钱 并打印涨前和涨后的薪水
*/
create or replace procedure raiseSalary(eno in number)
as
psal emp.sal%type;
begin
--涨前薪水
select sal into psal from emp where empno=eno;
--涨100
update emp set sal=sal+100 where empno=eno;
--要不要commit???
dbms_output.put_line(‘涨前:‘||psal||‘ 涨后:‘||(psal+100));
end;
/
第一个触发器
/*
成功插入员工后,自动输出“成功插入一个新员工”
CREATE [or REPLACE] TRIGGER 触发器名
{BEFORE | AFTER}
{DELETE | INSERT | UPDATE [OF 列名]}
ON 表名
PLSQL 块
*/
create or replace trigger sayNewEmp
after insert
on emp
begin
dbms_output.put_line(‘成功插入一个新员工‘);
end;
/
第一个存储过程
/*
create [or replace] PROCEDURE 过程名(参数列表)
AS
PLSQL子程序体;
打印Hello World
调用存储过程
1. exec sayHelloWorld();
2. begin
sayHelloWorld();
sayHelloWorld();
end;
/
*/
create or replace procedure sayHelloWorld
as
--说明部分
begin
dbms_output.put_line(‘Hello World‘);
end;
/
以上是关于oracle第三天的主要内容,如果未能解决你的问题,请参考以下文章