plsql编程学习语法和实例笔记.docx
- 文档编号:11945413
- 上传时间:2023-04-16
- 格式:DOCX
- 页数:13
- 大小:20.02KB
plsql编程学习语法和实例笔记.docx
《plsql编程学习语法和实例笔记.docx》由会员分享,可在线阅读,更多相关《plsql编程学习语法和实例笔记.docx(13页珍藏版)》请在冰豆网上搜索。
plsql编程学习语法和实例笔记
重点:
序列,游标,触发器
1、基本概念
游标是用来循环处理查询得到的每一列数据的方法,类似于while循环,提供集合处理之外的顺序处理能力。
触发器是在对数据表进行insertdeleteupdate等操作时,强制执行的后台操作。
多用于业务逻辑检查,数据检查、生成等。
sequence等同于序列号,每次取的时候sequence会自动增加,一般会作用于需要按序列号排序的地方。
2、实例
1)基本语法
--最简单的语句块
setserveroutputon;//用于输出显示
begin
dbms_output.put_line('HeloWorld');
end;
--一个简单的PL/SQL语句块
declare //声明变量,必须v_开头
v_namevarchar2(20);
begin
v_name:
='myname';//变量的赋值格式
dbms_output.put_line(v_name);
end;
--语句块的组成
declare
v_numnumber:
=0;
begin
v_num:
=2/v_num;
dbms_output.put_line(v_num);
exception //如果没有这部分,当出现异常的时候,就执行过不去
whenothersthen
dbms_output.put_line('error');
end;
--变量声明的规则
1):
变量名不能够使用保留字,如from、select等
2):
第一个字符必须是字母
3):
变量名最多包含30个字符
4):
不要与数据库的表或者列同名
5):
每一行只能声明一个变量
--常用变量类型
1):
binary_integer:
整数,主要用来计数而不是用来表示字段类型
2):
number:
数字类型
3):
char:
定长字符串
4):
varchar2:
变长字符串
5):
date:
日期
6):
long:
长字符串,最长2GB
7):
boolean:
布尔类型,可以取值为true、false和null
--变量声明,可以使用%type属性
declare
v_empno number(4);
v_empno2emp.empno%type;//表示该变量的类型和emp表中的empno字段保持一致。
v_empno3v_empno2%type;
begin
dbms_output.put_line('Test');
--Table变量类型 //类似于java中的数组
declare
typetype_table_emp_empnoistableofemp.empno%typeindexbybinary_integer;//声明一个类型
v_empnostype_table_emp_empno;
begin
v_empnos(0):
=100;
v_empnos
(2):
=200;
v_empnos(-1):
=300;
dbms_output.put_line(v_empnos(-1));
end;
--Record变量类型 //类似于java中的类,可以表示一整条记录
declare
typetype_record_deptisrecord
(
deptnodept.deptno%type,
dname dept.dname%type,
loc dept.loc%type
);
v_temptype_record_dept;
begin
v_temp.deptno:
=50;
v_temp.dname:
='aaa';
v_temp.loc:
='bj';
dbms_output.put_line(v_temp.deptno||''||v_temp.dname);
end;
不过当表增加了一个字段之后它就不管用了,可以选用下面的这种:
%rowtype
--使用%rowtype声明Record类型变量
declare
v_tempdept%rowtype;
begin
v_temp.deptno:
=50;
v_temp.dname:
='aaa';
v_temp.loc:
='bj';
dbms_output.put_line(v_temp.deptno||''||v_temp.dname);
--SQL语句的运用
1:
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
selectename,salintov_ename,v_salfromempwhereempno=7369;//必须返回记录,并且只能返回一条
dbms_output.put_line(v_ename||''||v_sal);
end;
2:
declare
v_empemp%rowtype;
begin
select*intov_empfromempwhereempno=7396;
dbms_output.put_line(v_emp.ename);
end;
3:
declare
v_deptnodept.deptno%type:
=50;
v_dnamedept.dname%type:
='aaa';
v_locdept.loc%type:
='bj';
begin
insertintodept2values(v_deptno,v_dname,v_loc); //insert、delete、update和sql是一样的,只是可以用变量
commit;
end;
4:
declare
v_deptnoemp2.deptno%type:
=10;
v_countnumber;
begin
updateemp2setsal=sal/2wheredeptno=v_deptno;
dbms_output.put_line(sql%rowcount||'条记录被影响');
commit;
end;
sql%rowcount 表示:
刚执行的最后一句sql影响到了多少条记录
--执行DDL语句
begin
executeimmediate'createtableT(nnnvarchar2(20)default''aaa'')';
end;
--if语句
--取出7369的薪水,如果<1200,则输出'low',如果<2000则输出'middle',否则'high'
declare
v_salemp.sal%type;
begin
selectsalintov_salfromempwhereempno='7369';
if(v_sal<1200)then
dbms_output.put_line('low');
elsif(v_sal<2000)then
dbms_output.put_line('middle');
else
dbms_output.put_line('high');
endif;
end;
--循环dowhile,while,loop,for循环
(1):
相当于do..while循环
declare
ibinary_integer:
=1;
begin
loop
dbms_output.put_line(i);
i:
=i+1;
exitwhen(i>=11);//循环结束的条件
endloop;
end;
(2):
while循环
declare
jbinary_integer:
=1;
begin
whilej<11loop
dbms_output.put_line(j);
j:
=j+1;
endloop;
end;
(3):
for循环
begin
forkin1..10loop
dbms_output.put_line(k);
endloop;
forkinreverse1..10loop //表示k的值从10到1
dbms_output.put_line(k);
endloop;
end;
--错误处理 (too_many_rows、no_data_found 等等)
declare
v_tempnumber(4);
begin
selectempnointov_tempfromempwhereempno=10;
exception
whentoo_many_rowsthen
dbms_output.put_line('太多记录了');
whenno_data_foundthen
dbms_output.put_line('没数据');
whenothersthen
dbms_output.put_line('error');
end;
--将错误信息存储到一张日志表中
(1):
createtableerrorlog
(
idnumberprimarykey,
errcodenumber,
errmsgvarchar2(1024),
errdatedate
);
(2):
createsequenceseq_errorlog_idstartwith1incrementby1;
(3):
declare
v_deptnodept.deptno%type:
=10;
v_errcodenumber;
v_errmsg varchar2(1024);
begin
deletefromdeptwheredeptno=v_deptno;
commit;
exception
whenothersthen
rollback;
v_errcode:
=SQLCODE; //是关键字,错误代码
v_errmsg:
=SQLERRM; //是关键字,错误信息
insertintoerrorlogvalues(seq_errorlog_id.nextval,v_errcode,v_errmsg,sysdate);
commit;
end;
2)序列
1、CreateSequence
(注释:
你需要有CREATESEQUENCE或CREATEANYSEQUENCE权限)
CREATESEQUENCEemp_sequence
INCREMENTBY1——每次加几个
STARTWITH1——从1开始计数
MAXVALUE——最大值值
NOMAXVALUE——不设置最大值
NOCYCLE——一直累加,不循环
CYCLE
CACHE10;
只要定义了emp_sequence,你就可以用使CURRVAL,NEXTVAL
CURRVAL=返回sequence的当前值
NEXTVAL=增加sequence的值,然后返回sequence值
例如:
emp_sequence.CURRVAL
emp_sequence.NEXTVAL
insertintodept(deptno,dname,loc)values(emp_sequence.nextval,'物流部','苏州');
//查询序列的当前值
selectemp_sequence.currvalfromdual;
可以使用sequence的地方:
。
不包含子查询、snapshot、VIEW的SELECT语句
。
INSERT语句的子查询中
。
NSERT语句的VALUES中
。
UPDATE的SET中
可以看如下例子:
INSERTINTOempVALUES
(empseq.nextval,'LEWIS','CLERK',7902,SYSDATE,1200,NULL,20);
SELECTempseq.CURRVALFROMDUAL;
需要注意的是:
第一次NEXTVAL返回的是初始值;随后的NEXTVAL会自动增加你定义的INCREMENTBY值,然后返回增加后的值。
CURRVAL总是返回当前SEQUENCE的值,但是在第一次NEXTVAL初始化之后才能使用CURRVAL,否则会出错。
一次NEXTVAL会增加一次SEQUENCE的值,所以如果你在同一个语句里面使用多个NEXTVAL,其值就会是不一样的。
-假如指定CACHE值,Oracle就可以预先在内存里面放置一些sequence,这样存取的快些。
cache里面的取完后,Oracle自动再取一组到cache.使用cache或许会跳号,比如数据库突然不正常down掉(shutdownabort),cache中的sequence就会丢失。
所以可以在createsequence的时候用nocache防止这种情况。
2、AlterSequence
你需要有sequence的owner,或者拥有ALTERANYSEQUENCE权限才能改动sequence.可以alter除start至以外的所有sequence参数。
如果想要改变start值,必须dropsequence再re-create.
Altersequence示例:
ALTERSEQUENCEemp_sequenceINCREMENTBY10MAXVALUE10000CYCLE--到10000后从头开始NOCACHE;
可以影响Sequence的初始化参数:
SEQUENCE_CACHE_ENTRIES=设置能同时被cache的sequence数目。
3、DropSequence
DROPSEQUENCEorder_seq;
3)触发器
--触发器
不能直接执行,必须依附在某张表上
createtableemp2_log
(
unamevarchar2(20),
actionvarchar2(10),
atimedate
);
createorreplacetriggertrig
afterinsertordeleteorupdateonemp2foreachrow
//foreachrow的作用:
每条记录发生insert,delete,update的时候都会执行触发器,
如果没有foreachrow,那么只会触发一次。
begin
ifinsertingthen
insertintoemp2_logvalues(USER,'insert',sysdate);
elsifupdatingthen
insertintoemp2_logvalues(USER,'update',sysdate);
elsifdeletionthen
insertintoemp2_logvalues(USER,'delete',sysdate);
endif;
end;
updateemp2setsal=sal*2wheredaptno=30;
select*fromemp2_log;
droptriggertrig;
--触发器的一个应用例子
(不能只更新dept表中的deptno,因为emp中有引用deptno)
createorreplacetriggertrig
afterupdateondeptforeachrow
begin
updateempsetdeptno=:
NEW.deptnowheredeptno=:
OLD.deptno;
end;
4)游标
--游标
1:
用游标取一条记录
declare
cursorcis //声明一个游标,这时候不会真正执行后面的查询语句,要等到打开游标的时候才执行
select*fromemp;
v_empc%rowtype;
begin
openc;
fetchcintov_emp;
dbms_output.put_line(v_emp.ename);
closec;
end;
2:
结合循环取出多条记录
(1):
do..while循环
declare
cursorcis
select*fromemp;
v_empc%rowtype;
begin
openc;
loop
fetchcintov_emp;
exitwhen(c%notfound);//当最近一次fetch没有返回记录
dbms_output.put_line(v_emp.ename);
endloop;
closec;
end;
(2):
while循环
declare
cursorcis
select*fromemp;
v_empemp%rowtype;
begin
openc;
fetchcintov_emp;
while(c%found)loop
dbms_output.put_line(v_emp.ename);
fetchcintov_emp;
endloop;
closec;
end;
(3):
for循环
declare
cursorcis
select*fromemp;
begin
forv_empincloop //for循环会自动打开和关闭游标,还会自动fetch..into
dbms_output.put_line(v_emp.ename);
endloop;
end;
--带参数的游标
declare
cursorc(v_deptnoemp.deptno%type,v_jobemp.job%type)
is
selectename,salfromempwheredeptno=v_deptnoandjob=v_job;
begin
forv_tempinc(30,'clerk')loop
dbms_output.put_line(v_temp.ename);
endloop;
end;
--可更新的游标
declare
cursorc
is
select*fromemp2forupdate;
begin
forv_tempincloop
if(v_temp.sal<2000)then
updateemp2setsal=sal*2wherecurrentofc;
elsif(v_temp.sal=5000)then
deletefromemp2wherecurrentofc;
endif;
endloop;
commit;
end;
5)存储过程
存储过程:
带有名字的PL/SQL的程序块,没有返回值
createorreplacep
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- plsql 编程 学习 语法 实例 笔记