1、PL/SQL语句块
定义一个包含声明、执行和异常处理的语句块
查询EMP表中职工号7788的工资,输出工资的值并且如果工资小于3000那么把工资更改为3000,异常部分对NO_DATA_FOUND异常进行
处理,输出没有该员工。如果想运行缓冲区的内容,那么可以用RUN命令或者/命令;serveroutput需要设置为on
declare
v_sal emp.sal%type;
begin
select sal into v_sal from emp where empno=7369;
if v_sal<3000 then
update emp set sal=3100 where empno=7369;
end if;
exception
when no_data_found then
dbms_output.put_line('There is not such a employee');
end;
2、变量、数据类型和系统函数的使用
1)定义三个变量,一个变量的初始值为字符串‘你好,’第二个字符串赋值为‘我是XXX’,这里写上自己的名字,第三个变量
为前两个变量中的字符串连接之后的结果。输出第三个变量的值。(选做)
declare
v_n1 varchar2(20):='你好';
v_n2 varchar2(20):='我是张洋洋';
v_n3 varchar2(30):=v_n1||v_n2;
begin
dbms_output.put_line(v_n3);
end;
2)将自己的名字作为字符串求出其长度,将长度与数字2进行比较,如果不大于2,输出‘我的名字是两个字’。(选做)
declare
v_n varchar2(20):='张洋洋';
begin
if length(v_n)<=2 then
dbms_output.put_line('我的名字是两个字');
end if;
end;
3)定义三个变量,分别用来存储emp表中的ename,sal,job三个列的值,并对其进行输出;要求用两种方式实现
(%type类型和非%type类型)。
declare
cursor c_emp is select ename,sal,job from emp;
v_emp c_emp%rowtype;
begin
open c_emp;
loop
fetch c_emp into v_emp;
exit when c_emp%notfound;
dbms_output.put_line(v_emp.ename||' '||v_emp.sal||' '||v_emp.job);
end loop;
close c_emp;
end;
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
v_job emp.job%type;
cursor v_emp is select ename,sal,job from emp;
begin
open v_emp;
loop
fetch v_emp into v_ename,v_sal,v_job;
exit when v_emp%notfound;
dbms_output.put_line(v_ename||' '||v_sal||' '||v_job);
end loop;
close v_emp;
end;
declare
v_ename varchar2(20);
v_sal varchar2(20);
v_job varchar2(20);
cursor v_emp is select ename,sal,job from emp;
begin
open v_emp;
loop
fetch v_emp into v_ename,v_sal,v_job;
exit when v_emp%notfound;
dbms_output.put_line(v_ename||' '||v_sal||' '||v_job);
end loop;
close v_emp;
end;
4)创建一个记录类型v_record,类型包含v_name,v_salary,v_job,v_deptno等分量,要求记录类型中各个分量的数据类型
和emp表中ename,sal,job,deptno列的数据类型一致(%type实现)。创建一个变量,变量类型为v_ record,读取EMP表
中职工号为7788的ename,sal,job,deptno为该变量赋值,输出该变量的值。
declare
cursor v_emp is select ename,sal,job,deptno from emp where empno=7788;
v_record v_emp%rowtype;
begin
open v_emp;
fetch v_emp into v_record;
dbms_output.put_line(v_record.ename||' '||v_record.sal||' '||v_record.job||' '||v_record.deptno);
close v_emp;
end;
3、条件语句的使用
分别用IF语句和CASE语句实现以下要求:输入一个员工号,修改该员工的工资,如果该员工职位是CLERK,工资增加100;
若为SALESMAN,工资增加160;若为ANALYST,工资增加200;否则增加300。
1.if-else实现
declare
v_empno emp.empno%type;
v_job emp.job%type;
v_increment number(4);
begin
v_empno:=&x;
select job into v_job from emp where empno=v_empno;
if v_job = 'CLERK'then v_increment:=100;
elsif v_job = 'SALESMAN' then v_increment:=160;
elsif v_job = 'ANALYST' then v_increment:=200;
else v_increment:=300;
end if;
update emp set sal=sal+v_increment where empno=v_empno;
end;
2.case实现
declare
v_empno emp.empno%type;
v_job emp.job%type;
v_increment number(4);
begin
v_empno:=&x;
select job into v_job from emp where empno=v_empno;
case v_job
when 'CLERK' then v_increment:=100;
when 'SALESMAN' then v_increment:=160;
when 'ANALYST' then v_increment:=200;
else v_increment:=300;
end case;
update emp set sal=sal+v_increment where empno=v_empno;
end;
4、循环的使用
1)使用循环实现,输出100以内所有个位上是7的整数(7,17,27...)。
declare
v_number number(4) := 1;
begin
loop
if mod(v_number,10)=7 then
dbms_output.put_line(v_number);
end if;
v_number := v_number + 1;
exit when v_number >100;
end loop;
end;
2)创建一张包含两个列的表,使用循环向该表添加10行数据,第一列添加从10000开始递增100的编号,第二列添加字符串
'hello world!'。(选做)
create table test1(
v_num number(6),
v_text varchar(20)
);
declare
v_num number(6):=10000;
begin
loop
insert into test1 values(v_num,'hello world!');
v_num := v_num + 100;
exit when v_num > 11000;
end loop;
end;
5、游标的使用
1)分别用简单循环、WHILE循环、FOR循环以及显式游标统计并输出各个部门的人数以及平均工资;
1.loop简单循环
declare
cursor c_emp is select count(*) c_deptno,avg(sal) c_avgsal from emp group by deptno;
v_dept c_emp%rowtype;
begin
open c_emp;
loop
fetch c_emp into v_dept;
exit when c_emp%notfound;
dbms_output.put_line(v_dept.c_deptno||' '||v_dept.c_avgsal);
end loop;
close c_emp;
end;
2.while循环
declare
cursor c_emp is select count(*) c_deptno,avg(sal) c_avgsal from emp group by deptno;
v_dept c_emp%rowtype;
begin
open c_emp;
fetch c_emp into v_dept;
while c_emp%found loop
dbms_output.put_line(v_dept.c_deptno||' '||v_dept.c_avgsal);
fetch c_emp into v_dept;
end loop;
close c_emp;
end;
3.for循环
declare
cursor c_emp is select count(*) c_deptno,avg(sal) c_avgsal from emp group by deptno;
begin
for v_dept in c_emp loop
dbms_output.put_line(v_dept.c_deptno||' '||v_dept.c_avgsal);
end loop;
end;
2)使用循环和游标实现,查询部门编号为10的员工信息,将查询结果按照员工编号从大到小的顺序排列,输出倒数第二行
记录。(选做)
declare
v_num number(4);
cursor c_emp is select * from emp where deptno=10 order by empno desc;
v_emp c_emp%rowtype;
begin
select count(*) into v_num from emp where deptno=10 order by empno desc;
open c_emp;
for v_counter in 1..v_num loop
fetch c_emp into v_emp;
if v_counter = v_num -1 then
dbms_output.put_line(v_emp.empno||' '||v_emp.ename||' '||v_emp.job||' '||v_emp.mgr||' '||v_emp.hiredate||' '||
v_emp.sal||' '||v_emp.comm||' '||v_emp.deptno);
end if;
end loop;
end;
3)使用隐式游标实现以下要求:修改部门号为50的部门地址为‘BEIJING’。如果该部门不存在,则向dept表中插入一个部门号为50,
地址为‘BEIJING’的记录。 (选做)
declare
begin
update dept set loc='BEIJING' where deptno=50;
if sql%notfound then
insert into dept(deptno,loc) values(50,'BEIJING');
end if;
end;
6、创建一个显示雇员总人数的存储过程emp_count,并执行该存储过程
创建:
create or replace procedure emp_count
as
v_count number(4);
begin
select count(*) into v_count from emp;
dbms_output.put_line(v_count);
end;
执行:
execute emp_count();
7、编写显示雇员信息的存储过程EMP_LIST,并引用EMP_COUNT存储过程
1.创建
create or replace procedure emp_list
as
cursor emp_list is select * from emp;
begin
for v_emp in emp_list loop
dbms_output.put_line(v_emp.empno||' '||v_emp.ename||' '||v_emp.job||' '||v_emp.mgr||' '||v_emp.hiredate||' '||
v_emp.sal||' '||v_emp.comm||' '||v_emp.deptno);
end loop;
end;
2.执行
execute emp_list();
8、创建函数,实现功能为:在scott.emp表和scott.dept表中查询出任意给定职工号的职工姓名及职工所在部门的名称。
1.创建
create or replace function emp_dept(
e_empno emp.empno%type,
e_name out varchar2)
return dept.dname%type
as
d_name dept.dname%type;
begin
select ename,dname into d_name,e_name from emp,dept where emp.empno=e_empno and dept.deptno in
(select deptno from emp where empno=e_empno);
return d_name;
end emp_dept;
2.调用
declare
e_empno emp.empno%type;
d_name dept.dname%type;
e_name emp.ename%type;
begin
e_empno:=&x;
d_name:=emp_dept(e_empno,e_name);
dbms_output.put_line(e_name||' '||d_name);
end;
9、创建触发器,实现更新dept表中的deptno值,级联更新emp表中相应值。
create or replace trigger dept_emp_dml
before update on dept
for each row
begin
if UPDATING then
update emp set deptno=:new.deptno where deptno=:old.deptno;
end if;
end dept_emp_dml;
10、对存储过程、函数及触发器实现查看、修改、删除等基本操作。
1.对存储过程的
查看:select object_name,status from user_objects where object_type='PROCEDURE';
修改:CREATE OR REPLACE PROCEDURE procedure_name;
删除:drop PROCEDURE emp_list;
2.对函数的
查看:select object_name,status from user_objects where object_type='FUNCTION';
修改:CREATE OR REPLACE FUNCTION function_name;
删除:drop FUNCTION emp_dept;
3.对触发器的
查看:select trigger_name,trigger_type,table_name,trigger_body from user_triggers;
修改:CREATE OR REPLACE TRIGGER trigger_name;
删除:DROP TRIGGER dept_emp_dml;
end dept_emp_dml;
11、创建一个包mypackage,声明该包有一个过程update_sal和一个函数get_YearSal
create or replace package mypackage is
procedure update_sal(name varchar2,newsal number);
function get_YearSal(name varchar2) return number;
end;
create or replace package body myPackage is
rprocedure update_sal(name varcha2,newsal number) is
begin
update emp set sal=newSal where ename=name;
end;
function get_YearSal(name varchar2) return number is
v_sal number(7,2);
begin
select sal*12+nvl(comm,0) into v_sal from emp where ename=name;
return v_sal;
end;
end;
调用执行包中的存储过程或函数
Begin
mypackage.update_sql(’smith’,5000);
mypackage.get_YearSal(’smith’);
end;
12、假设有这样一张用户表表结构如下:UserInfo(id ,username,userPass),希望向表中增加数据时,表中id列的数字自动生成。(选做)
1)第一步创建序列,要求开始的数字为1,每次递增1,按顺序产生序列值;
创建表:
Create table UserInfo(
id number(4),
username varchar2(20),
userpass varchar2(20)
);
创建序列:
create sequence UserInfo_Id
increment by 1
start with 1
minvalue 1
maxvalue 999999999;
更改数据库的“延迟段创建”特性为false(需要有相应的权限)
ALTER SYSTEM SET deferred_segment_creation=FALSE;
测试:
declare
begin
for v_counter in 1..10 loop
insert into UserInfo (id,username,userpass) values(UserInfo_Id.NEXTVAL,'suns','123456');
end loop;
end;
2)第二步创建一个触发器,向用户表中插入数据的时候触发触发器,在触发器内部调用序列并生成一个序列值赋值给表的id列。
create or replace trigger userinfo_dml
before insert on UserInfo
for each row
begin
select UserInfo_Id.nextval into :new.id from dual;
end userinfo_dml;