PL/SQL
一、函数的应用
1.变量的声明与赋值
--声明一个变量,并赋值、打印
declare
str varchar2(30);
sname emp.ename%type;--声明一个与emp表的ename属性一致的类型
ctable emp%rowtype;--声明一个与emp表相同的行类型
begin
str:='&请输入:';--手动输入,是一种动态赋值
select ename into sname from emp whereempno=7369;
select * into ctable from emp whereempno=7499;
dbms_output.put_line('str='||str);
dbms_output.put_line('sname='||sname);
dbms_output.put_line('ename='||ctable.ename);
end;
2.if语句的使用
--if 取出7369的薪水,判断是否纳税
declare
salary emp.sal%type;
begin
select sal into salary from emp whereempno=7369;
if salary>=3000 then
dbms_output.put_line('需要纳税');
else --elsif相当于java里elseif
dbms_output.put_line('需努力');
end if;
end;
--case 的两种用法
1>.declarestr varchar2(10);
begin
str:='A';
case str
when'A' then dbms_output.put_line('优秀');
when 'B' thendbms_output.put_line('良好');
when 'C' thendbms_output.put_line('好');
when 'D' thendbms_output.put_line('一般好');
when 'E' thendbms_output.put_line('不好');
else dbms_output.put_line('很不好');
end case;
end;
2>.
declare mysalnumber(6,2);
eno number(6);
begin
eno:=7369; --直接赋值
select sal intomysal from emp where empno=eno; --这也是一种赋值
case when mysal>3500 then dbms_output.put_line('交税');
when mysal=3500 thendbms_output.put_line('刚好');
when mysal<3500 thendbms_output.put_line('努力');
else dbms_output.put_line('其他');
end case;
end;
3.Loop While For 三种循环
1> --输出1..100;
declare inumber(6):=1;
mysumnumber(6):=0;
begin
<<b_loop>>--给loop取个名字
loop
dbms_output.put_line(i);
mysum:=mysum+i;
exit b_loopwhen i=200; --跳出循环
i:=i+1;
end loop;
dbms_output.put_line(mysum);
end;
declare inumber(6):=1;
mysumnumber(6):=0;
begin
while i<=100 loop
mysum:=mysum+i;
i:=i+1;
end loop;
dbms_output.put_line(mysum);
end;
declare
mysumnumber(6):=0;
begin
for i in 1..100 loop --1..100这两个参数均可使用变量
mysum:=mysum+i;
--i:=i+1;
end loop;
dbms_output.put_line(mysum);
end;
4.Oracle两种常见的报错
too_many_rows //太多行错误
no_data_found //没找到数据
二、游标
游标分为隐式游标、显示游标、REF游标。
1>.隐式游标
隐式游标无需我们申明、创建、使用,它全由系统自动完成,我们在JDBC中使用的ResultSet对象就是这种用法。
2>显示游标
--pl/sql 声明(declare) 代码(begin end) 异常(exception)
declare
cursor myc is select * from emp;--声明游标
myr emp%rowtype;
begin
open myc;--打开游标
--使用游标:fetch (从游标中提取一行)
loop
fetch myc intomyr;
exit when myc%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myc;
end;
--带条件的游标:打印2500以下的员工信息
declare
cursor myc isselect * from emp where sal<2500;
myr emp%rowtype;
begin
open myc;
loop
fetch myc into myr;
exit when myc%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myc;
end;
--由用户指定查询的薪水:带参数的游标
declare
cursor myc(mysal number) is select * from emp wheresal<mysal;
myr emp%rowtype;
issalnumber(8,2);
begin
issal:=&请输入;
open myc(issal);
loop
fetch myc into myr;
exit when myc%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myc;
end;
--for 循环游标
declare
cursor myc(mysalnumber) is select * from emp where sal<mysal;
begin
for myr in myc(2500) loop
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
end;
3.REF游标
declare
type myc is ref cursor
return emp%rowtype;--有返回值表示它是强类型,无则是弱类型
mycd myc;
myr emp%rowtype;
begin
open mycd for select * from emp;
loop
fetch mycd into myr;
exit when mycd%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close mycd;
end;
--动态ref
declare
type myc is refcursor;
myce myc;
myr emp%rowtype;
mysalnumber(7,2);
begin
mysal:=2500;
open myce for 'select * from emp where sal>:1' using mysal;--“:1”表预备的第一个参数,相当于JDBC中的预备语句的“?”
loop
fetch myce into myr;
exit when myce%notfound;
dbms_output.put_line('名字'||myr.ename||' 薪水:'||myr.sal);
end loop;
close myce;
end;
三、同义词、授权、序列、视图、索引、
1.同义词
--创建同义词(需授权)
create or replacesynonym a for scott.emp;
--使用同义词
select * from a;
--删除同义词
drop synonym a;--为什么只删除该同义词的内容,此框架还存在,那应该怎么删除?
2、授权
--授权
grant create synonym to scott;
--收权
revoke create synonym from scott;
3.序列
--创建序列(它不能重复创建)
create sequence seq
start with 1
increment by 3
maxvalue 100
minvalue 1
cache 20;
create sequenceseq;--这也可以,默认为从1开始,每次加1;
--使用序列
select seq.nextvalfrom dual;
select seq.currvalfrom dual;
--删除序列
drop sequence seq;
--修改序列里的内容(不能修改其序列名,修改后也就不是此序列)
-- Alter sequence
alter sequence SEQ
minvalue 2
maxvalue 399
increment by 3;
-- Modify thelast number
alter sequenceSEQ increment by 2 nocache;
selectSEQ.nextval from dual;
alter sequenceSEQ increment by 3 cache 20;
4、视图
--创建视图(需授权)
视图是一个虚表,数据表删除了,但它还存在,只是不能运行,也就是说,视图实际是一段select语句,它能保证数据的安全性。理论上视图是可修改,但实际上不去修改,视图可以嵌套视图,但不能无穷嵌套。并且sqlserver 只能嵌套32层。
create or replace view v_emp as select * from emp;
--使用视图
select * fromv_emp;
--删除视图
drop view v_emp;
5、索引(index)
索引:是数据库内部编排数据的一种方法,两个列可以创建同一个索引,称为组合索引,表的每一个列都可以创建索引。索引依附于表存在,表删除了,索引也没了;能提高查询速度,但会降低增、删、改的速度。索引非常占硬盘空间,若一个表里有五个列,100万行数据,有一个列加了索引,则硬盘除了保存那原先的100万行数据外,还要保存100万行索引数据,其中包含两列,一个是主键,一个是创建索引的那个列,也就意味着,表里每增加一个索引就会增加100万行索引数据。
6.
nvl(condition,value);此方法:若condition为空,则值用value的值来填充。
五、存储过程
存储过程:是一段预先编译好的存储在数据库里一段SQL语句集。
其优点:模块化,安全性,减少网络的流通量
--创建存储过程
create or replaceprocedure pname_1203(eno number)
as
myename varchar2(80);
mysal number(8,2);
begin
select ename,sal into myename,mysal fromemp where empno=eno
dbms_output.put_line('姓名'||myename||' 薪水为'||mysal);
end;
--使用存储过程
begin
pname_1203(7369);
end;
过程参数的三种模式:
IN: 用于接受调用程序的值,默认的参数模式
OUT: 用于向调用程序返回值
IN OUT: 用于接受调用程序的值,并向调用程序返回更新的值
--out 类型表示该值是从存储过程传到外面去的
create or replace procedurepname_1203a(eno number,myjob out varchar2)
as
myename varchar2(50);
begin
select ename,job into myename,myjob fromemp where empno=eno;
dbms_output.put_line('姓名是'||myename);
end;
注意:oracle里的子程序包括存储过程与函数。
六、程序包(package)
--包头的创建
create or replacepackage pname1203 is
procedure pr1203(eno number);
function fu1203(eno number)returnvarchar2;
end pname1203;
--包体的创建
create or replacepackage body pname1203 is
procedure pr1203(eno number)
is
myename varchar2(55);
begin
select ename into myename from emp whereempno=eno;
dbms_output.put_line('姓名是'||ename);
end pr1203;
function fu1203(eno number) return varchar2 is
myename varchar2(55);
begin
select ename into myename from emp whereempno=eno;
return myename||'hello';
end fu1203;
end pname1203;
--如何调用包里面的东西
select pname1203.fu1203(7369)from dual;
七、触发器
1.需记住的
(1).三种操作:delete update insert
(2).两个临时表: :new :old
:old表用来保存要删除时的数据,只有一行数据
:new表用来保存要插入时的数据,只有一行数据
更新时需要:old and :new 两个表都需要
(3).两个时间点: after before
(4).两种重要模式:行级 语句级(即表级)
(5).条件:when
2. --建立触发器:学生信息表中‘s25301'不能删除、修改; 插入时,
-- 检查名字叫'张洋洋'的不能添加 's25302'不能改
createor replace trigger t_stu
afterdelete or update or insert on stuinfo
for each row //这表示是行级触发器,若没写,则为表级触发器。
declaresno varchar2(40);
snamevarchar2(50);
begin
sno:=:old.stuno;
sname:=:new.stuname;
if deleting then
if sno='s25301' then
raise_application_error(-20009,'该学生不能动');//-20009是自定义错误,其自定义错误代码范围:-20000至-21000.
end if;
elsif updating then
if sno='s25302' then
raise_application_error(-20004,'该学生不能动');
end if;
elsif inserting then
if sname='张洋洋'then
raise_application_error(-20006,'该学生不能要');
end if;
end if;
end;
3.在插入数据时自动插入序列号
create or replace trigger t_stua
beforeinsert on tb_study
for eachrow
begin
--:new.sid:=mys1208.nextval; //11g版本可使用
select mys1208.nextval into :new.sid from dual; //10g可使用
end;