、SQLPLUS1引言SQL命令以下17个是作为语句开头的关键字:alterdroprevokeauditgrantrollback*commit*insertselectcommentlockupdatecreatenoauditvalidatedeleterename这些命令必须以“;”结尾带*命令句尾不必加分号,并且不存入SQL缓存区。SQL中没有的SQL*PLUS命令这些命令不存入SQL缓存区@definepause#delquit$describeremark/disconnectrunacceptdocumentsaveappendeditsetbreakexitshowbtitlegetspoolchangehelpsqlplusclearhoststartcolumninputtimingcomputelistttitleconnectnewpageundefinecopy------2数据库查询数据字典TAB用户创建的所有基表、视图和同义词清单DTAB构成数据字典的所有表COL用户创建的基表的所有列定义的清单CATALOG用户可存取的所有基表清单selectfromtab;
describe命令描述基表的结构信息describedeptselectfromemp;selectempno,ename,jobfromemp;selectfromdeptorderbydeptnodesc;逻辑运算符=!=或<>>>=<<=inbetweenvalue1andvalue2like%_innullnotnoin,isnotnull谓词in和notin有哪些职员和分析员selectename,jobfromempwherejobin('clerk','analyst');selectename,jobfromempwherejobnotin('clerk','analyst');谓词between和notbetween哪些雇员的工资在2000和3000之间selectename,job,salfromempwheresalbetween2000and3000;selectename,job,salfromempwheresalnotbetween2000and3000;谓词like,notlikeselectename,deptnofromemp
whereenamelike'S%';(以字母S开头)selectename,deptnofromempwhereenamelike'%K';(以K结尾)selectename,deptnofromempwhereenamelike'W___';(以W开头,后面仅有三个字母)selectename,jobfromempwherejobnotlike'sales%';(哪些雇员的工种名不以sales开头)谓词isnull,isnotnull没有奖金的雇员(即commision为null)selectename,jobfromempwherecommisnull;selectename,jobfromempwherecommisnotnull;多条件查询selectename,jobfromempwheredeptno=20andjob!='clerk';表达式/算术表达式选择奖金高于其工资的5%的雇员selectename,sal,comm,comm/salfromempwherecomm>.05*salorderbycomm/saldesc;日期型数据的运算addtwodaysto6Mar-876-Mar-872=8-Mar-87addtwohoursto6-Mar-876-Mar-872/24=6-Mar-87and2hrsadd15secondsto6-Mar-876-Mar-8715/(24*60*60)=6-Mar-87and15secs列名的别名
selectenameemployeefromempwheredeptno=10;(别名:employee)selectename,sal,comm,comm/sal"C/SRATIO"fromempwherecomm>.05*salorderbycomm/saldesc;SQL命令的编辑listorl显示缓冲区的内容list4显示当前SQL命令的第4行,并把第4行作为当前行,在该行号后面有个*。changeorc用新的内容替换原来在一行中第一次出现内容SQL>c/(...)/('analyst')/inputori增加一行或多行appendora在一行后追加内容del删除当前行删除SQL缓冲区中的当前行run显示并运行SQL缓冲区中的命令/运行SQL缓冲区中的命令edit把SQL缓冲区中的命令写到操作系统下的文本文件,并调用操作系统提供的编辑器执行修改。----------3数据操纵数据的插入insertintodeptvalues(10,'accounting','newyork');insertintodept(dname,deptno)values('accounting',10);从其它表中选择插入数据insertintoemp(empno,ename,deptno)selectid,name,departmentfromold_empwheredepartmentin(10,20,30,40);使用参数insertintodeptvalues(&;deptno,&;dname,&;loc);执行时,SQL/PLUS对每个参数将有提示用户输入参数对应日期型或字符型数据时,可在参数上加引号,输入时就可不用引号insertintodeptvalues(&;deptno,'&;dname','&;loc');
插入空值(NULL)insertintodeptvalues(50,'education',null);插入日期型数据日期型数据缺省格式:DD-MON-YYinsertintoemp(empno,ename,hiredate)values(7963,'stone','07-APR-87');系统时间:SYSDATEinsertintoemp(empno,ename,hiredate)values(7600,'kohn',SYSDATE);数据更新updateempsetjob='manager'whereename='martin';updateempsetjob='marketrep'whereename='salesman';updateempsetdeptno=40,job='marketrep'wherejob='salesman';数据删除deleteempwhereempno=765;更新的提交commit自动提交方式setautocommiton如果状态设为开,则使用inesrt,update,delete会立即提交。更新取消rollback两次连续成功的commit之间的操作,称为一个事务
------------4创建基表、视图创建基表createtabledept(deptnonumber(2),dnamechar(14),locchar(13));数据字典会自动更新。一个基表最多254列。表名列名命名规则:限制第一个字符必须是字母,后面可任意(包括$#但不能是逗号)。名字不得超过30个字符。唯一某一用户的基表名必须唯一,不能是ORACLE的保留字,同一基表的列名互不相同。使用双引号如果表名用双引号括起来,则可不满足上述规则;只有使用双引号,才能区别大、小写;命名时使用了双引号,在以后的操作也必须使用双引号。数据类型:char(n)(不得超过240字符)number(n,d)datelong(最多65536字符)raw(二进制原始数据)空值处理有时要求列值不能为空createtabledept(deptnonumber(2)notnull,dnamechar(14),locchar(13));在基表中增加一列altertabledeptadd(headcntnumber(3));修改已有列属性altertabledept
modifydnamechar(20);注:只有当某列所有值都为空时,才能减小其列值宽度。只有当某列所有值都为空时,才能改变其列值类型。只有当某列所有值都为不空时,才能定义该列为notnull。例:altertabledeptmodify(locchar(12));altertabledeptmodifylocchar(12);altertabledeptmodify(dnamechar(13),locchar(12));创建视图createviewmanagersasselectename,job,salfromempwherejob='manager';为视图列名取别名createviewmydept(person,title,salary)asselectename,job,salfromempwheredeptno=10;withcheckoption选项使用withcheckoption,保证当对视图插入或更新数据时,该数据必须满足视图定义中select命令所指定的条件。createviewdept20asselectename,job,sal,deptnofromempwheredeptno=20withcheckoption;在做下述操作时,会发生错误updatedept20setdeptno=30whereename='ward';基表、视图的拷贝createtableemp2asselectfromemp;基表、视图的删除droptable表名dropview视图名----------
5SQLPLUS报表功能SQL*PLUS的一些基本格式命令columndeptnoheadingdepartmentcolumnenameheadingnamecolumnsalheadingsalarycolumnsalformat$99,999.00ttitlesamplereportfor|hitechcorpbtitlestrictlyconfidentialbreakondeptnocomputesumofsalondeptnorun表头和表尾ttitlesamplereportfor|hitechcorpbtitlerightstrictlyconfidential“|”表示换行,结尾不必加分号选项有三种:leftrightcenter使用TTITLE,系统将自动地在每页的顶部显示日期和页号。TTITLET和BTITLE命令有效,直至重新设置表头或表尾,或退出SQL*PLUS。下面命令使标题语句失效TTITLEOFFBTITLEOFF列名column命令定义用于显示列名若名字为一个单词,不必加引号columnenameheadingemployeecolumnenameheading'employee|name'(|为换行)取消栏定义columnenameclear
列的格式columnenameformatA15columnsalformat$9,999.99columncommlikesallike子句,使得某一列的格式参照另一列格式,它拷贝列名及其格式控制记录显示分组顺序breakondeptno(不显示重复值)selectdeptno,enamefromemporderbydeptno;(ORDERBY子句用于控制BREAK)显示为10clarkniller20smithscott30allenblake每次只有一个BREAK命令起作用,但一次可以在多个列上使用BREAK命令breakon列名1on列名2记录分组breakondeptnoskip2selectdeptno,enamefromemporderbydeptno;每个deptno之间空两行clearbreak(取消BREAK命令)breakonpage(每次从一新页开始)breakonreport(每次从一新报表开始)breakonpageonreport(联合使用)分组计算breakondeptnoskip2
computesumofsalondeptno计算每个部门的工资总和skip子句使部门之间的信息分隔开其他计算命令computeavgofsalondeptno(平均值)count非空值的总数MAX最大值MIN最小值STD标准偏差VAR协方差NUMBER行数使compute命令失效一旦定义了COMPUTE,则一直有效,直到关闭COMPUTE(clearcompute)SQL/PLUS环境命令show选项(显示当前参数设置情况)showall(显示全部参数)设置参数set选项值或开关setautocommitonSET命令包括setautocommit{off|on|immediate}(自动提交,OFF缺省)setecho{off|on}(命令文件执行,是否在终端上显示命令本身,OFF缺省)setfeedback{off|on}(ON:查询结束时,给出结果,记录数的信息,缺省;OFF:无查询结果,记录数的信息)setheading{off|on}(ON:列的头标在报表上显示,缺省;OFF:不在报表上显示)setlinesize{n}一行显示的最大字符数,缺省为80
setpagesize{n}每页的行数,缺省是14setpause{off|on|text}(ON:当报表超过一页时,每显示一屏就暂停显示,等待用户打回车键,再接着显示;OFF:页与页不停顿,缺省;text:页与页停顿,并向用户提示信息)SETBUFFERbuffer设置当头的命令缓冲区,通常情况下,SQL命令缓冲区已为当前缓冲区。由于SQL命令缓冲区只能存放一条SQL命令,所以可用其它缓冲区来存放SQL命令和SQL*PLUS命令。经常用到的设置可放在login.sql文件中。SETNULLsetnull'nodata'selectename,commfromempwheredeptno=30;把部门30中无佣金雇员的佣金显示为“NODATA”。setnull是SQL*PLUS命令,用它来标识空值(NULL),可以设置为任意字符串。存盘命令SAVEsave文件名input1selectempno,ename,job2fromemp3wherejob='analyst'saveresearch目录中会增加一个research.sql文件。编辑命令EDITeditEDIT编辑当前缓冲区中的内容。编辑一个文件editresearch
调入命令GETgetresearch把磁盘上的文件内容调入缓冲区,并显示在屏幕上,文件名尾不必加.sql。START命令运行指定的文件startresearch输出命令SPOOLspooltryfile不仅可以使查询结果在屏幕上显示,还可以使结果存入文件停止向文件输出spooloff把查询结果在打印机上输出,先把它们存入一个文件中,然后不必使用SPOOLOFF,而用:spooloutSPOOLOUT关闭该文件并在系统缺省的打印机上输出制作报表举例edittryfilesetechooffsetautocommitonsetpagesize25insertintoemp(empno,ename,hiredate)values(9999,'geiger',sysdate);insertintoemp(empno,ename,deptno)values(3333,'samson',20);spoolnewempselectfromempwheredeptno=20ordeptnoisnull/spooloffsetautocommitoff用start命令执行这个文件-----6函数字符型函数
initcap(ename);将ename中每个词的第一个字母改为大写。如:jacksmith--JackSmithlength(ename);计算字符串的长度。substr(job,1,4);其它lowerupperleast取出字符串列表中按字母排序排在最前面的一个串greatest取出字符串列表中按字母排序排在最后的一个串日期函数add_month(hiredate,5)在雇佣时间上加5个月month_between(sysdate,hiredate)计算雇佣时间与系统时间之间相差的月数next_day(hiredate,'FRIDAY')计算受雇日期之后的第一个星期五的日期例selectename,sal,next_day(sysdate,'FRIDAY')as_offromempwheredeptno=20;(as_of是别名)如果不用to_char函数,日期在ORACLE中的缺省格式是'DD_MON_YY'to_char(date,datepicture)selectename,to_char(hiredate,'DyMondd,yyyy')hiredfromempwheredeptno=10;to_date(字符串,格式)insertintoemp(empno,ename,hiredate)values(7999,'asms',to_date('070387083000','MMDDYYHHMISS'));日期型数据的格式dd12dyfridayfridayddspthtwelfthmm03monmar
monthmarchyy87yyyy1987例Mar12,1987'Mondd,yyyy'MAR12,1987'MONdd,yyyy'ThursdayMARCH12'DayMONTHdd'Mar1211:00am'Monddhh:miam'Thu,thetwelfth'Dy,"the"ddspth'算术函数least(v1,v2)selectename,empno,mgr,least(empno,mgr)lownumfromempwhereempno0trunc(sal,0)取sal的近似值(截断)空值函数nvl(v1,v2)v1为列名,如果v1不是空值,nvl返回其列值。v1为空值,返回v2的值。聚组函数selectsum(comm)fromemp;(返回一个汇总信息)不能把sum用在select语句里除非用groupby字符型、日期型、数字型的聚组函数minmaxcount可用于任何数据类型selectmin(ename)fromemp;selectmin(hiredate)fromemp;selectmin(sal)fromemp;
有多少人有工作?selectcount(job)fromemp;有多少种不同的工种?selectcount(distinctjob)fromemp;countdistinct计算某一字段中不同的值的个数其它聚组函数(只用于数字型数据)avg计算平均工资selectavg(sal)fromemp;stddev计算工资的平均差selectstddev(sal)fromemp;sum计算总工资selectsum(sal)fromemp;groupby子句selectdeptno,sum(sal),avg(sal)fromempgroupbydeptno;按多个条件分组每个部门的雇员数selectdeptno,count()fromempgroupbydeptno;每个部门的每个工种的雇员数selectdeptno,job,count(*)fromempgroupbydeptno,job;满足条件的分组(where是针对select的,having是针对groupby的)哪些部门的工资总和超过了9000selectdeptno,sum(sal)
fromempgroupbydeptnohavingsum(sal)>9000;select小结除去职员,哪些部门的工资总和超过了8000selectdeptno,sum(sal)fromempwherejob!='clerk'groupbydeptnohavingsum(sal)>8000orderbysum(sal);------7高级查询等值联接selectempno,ename,job,emp.deptno,dnamefromemp,deptwhereemp.deptno=dept.deptno;外联接selectename,dept.deptno,locfromemp,deptwhereemp.deptno(+)=dept.deptno;如果在dept.deptno中有的数值,在emp.deptno中没有(如deptno=40),则作外联接时,结果中会产生一个空值自联接:同一基表的不同行要做联接,可使用自联接指出每个雇员的经理名字selectworker.ename,manager.enamemanagerfromempworker,empmanagerwhereworker.mgr=manager.empno;非等值联接哪些雇员的工资属于第三级别selectename,salfromemp,salgradewheregrade=3andsalbetweenlosalandhisal;(基表salgrade:gradelosalhisal)集合运算行的连接集合运算把2个或多个查询结果合并为一个
union-setunionRowsoffirstqueryplusofsecondquery,lessduplicaterowsintersect-setintersectionRowsbothquerieshaveincommonminus-setdifferencerowsuniquetothefirstquery介绍几个视图accountviewenamesaljobsalesviewenamesaljobresearchviewenamesaljobunion运算返回一个查询结果中有但又不重要的行,它将基表或视图中的记录合并在一起所有部门中有哪些雇员工资超过2000对应列的数据类型必须相同selectename,salfromaccountwheresal>2000unionselectename,salfromresearchwheresal>2000unionselectename,salfromsaleswheresal>2000;intersect运算返回查询结果中相同的部分各个部门中有哪些相同的工种selectjobfromaccountintersectselectjobfromresearchintersect
selectjobfromsales;minus运算返回在第一个查询结果中与第二个查询结果不相同的那部分行记录。有哪些工种在财会部中有,而在销售部中没有?selectjobfromaccountminusselectjobfromsales;子查询slectename,deptnofromempwheredeptno=(selectdeptnofromempwhereename='smith');多级子查询selectename,job,salfromempwherejob=(selectjobfromempwhereename='clark')orsal>(selectsalfromempwhereename='clark');多个基表与子查询selectename,job,salfromemp,deptwhereloc='newyork'andemp.deptno=dept.deptnoandsal>(selectsalfromempwhereename='scott');子查询中使用聚组函数selectename,hiredatefromempwherehiredate=
(selectmin(hiredate)fromemp);8授权系统权限DBA所有权限RESOURCE注册,创建新的基表CONNECT,注册,查询只有DBA才有权创建新的用户grantconnecttoscottidentifiedbytiger;DBA或用户自己可以改变用户口令grantconnecttoscottidentifiedbyleopard;基表权限1有两种方法获得对基表操作的权限创建自己的基表获得基表创建用户的许可grantselect,insertonemptoscott;这些权限有selectinsertupdatedeletealterindex把所有权限授于他人grantallonemptoscott;同义词selectfromscott.emp创建同义词为用户allen的EMP基表创建同义词employeecreatesynonymemployeeforallen.emp基表权限2你可以使其他用户有这样的权力,即其他用户可以把你的基表权限授予他人grantall
onemptoscottwithgrantoption;收回权限系统权限只有被DBA收回基表权限随时都可以收回revokeinsertonempfromscott;------9索引建立索引createindexemp_enameonemp(ename);删除索引dropindexemp_ename;关于索引只对较大的基表建立索引(至少50条记录)建立索引之前插入数据对一个基表可建立任意多个索引一般是在作为主键的列上建立索引建立索引之后,不影响SQL命令的执行建立索引之后,ORACLE自动维护和使用索引保证数据唯一性提高执行速度的同时,索引还可以保证每个记录中的每个列值是不重复的。createuniqueindexemp_empnoonemp(empno);-----练习和答案有没有工资比奖金多的雇员?如果有,按工资的降序排列。如果有两个以上的雇员工资相同,按他们的名字排序。selectenameemployee,salsalary,commcommisionfromempwheresal>commorderbysaldesc,ename;
列出有关雇员、奖金占收百分比的信息。要求显示时列名意义明确,按雇员排序,不包括奖金未知的雇员。selectenameemployee,(comm/(comm+sal))100incentivefromempwherecommisnotnullorderbyename;在chicago(部门30)工作的所有雇员的工资上涨10%。updateempsetsal=1.1*salwheredeptno=30;updateempsetsal=1.1*salwheredeptno=(selectdeptnofromdeptwhereloc='chicago');为hitech公司新建一个部门,编号为50,其它信息均不可知。insertintodept(dname,deptno)values('faclities',50);创建视图,三个列名,其中不包括职员信息createviewemployee("employeename","employeenumber","employeejob")asselectename,empno,jobfromempwherejob!='clerk';制作工资报表,包括雇员、受雇时间(按星期计算),工资和部门编号,一页显示一个部门的信息,每页尾,显示该页的工资之和以及受雇时间之和,报表结尾处,显示所有雇员的工资总和以及受雇时间总和,工资按美元计算,受雇时间按星期计算,每页的上方应有标题。ttitle'service'breakondeptnoonpageonreportcomputesumofsalondeptnocomputesumofsalonreportcomputesumofservice_lengthondeptnocomputesumofservice_lengthonreportcolumnsalformat$99,999.00columnservice_lengthformat9999selectdeptno,enameemployee,(sysdate-hiredate)/7service_length,sal
fromemporderbydeptno;制作报表,包括雇员、总收入和受佣日期,且:的第一个字母必须大写,雇佣日期格式为MM/DD/YYYY,总收入包括没有奖金的雇员的总收入,按字母顺序排列。col"hiredate"formatA12col"employee"formatA10col"compensation"format$99,999.00selectinitcap(ename)"employee",(sal+nvl(comm,0))"compensation",to_char(hiredate,'MM/DD/YYYY')"hiredate"fromemporderbyename;列出有超过7个周边国家的国家名字和面积。selectnation,areafromnationwherecodein(selectnation_codefrombordergroupbynation_codehavingcount(*)>7);列出所有面积大于等于日本的岛国的国名和人口。selectnation,populationfromnation,borderwherecode=nation_code(+)andnation_codeisnullandarea>=(selectareafromnationwhereupper(nation)='JAPAN');列出所有边界在其它国家中的国名,并且显示其边界国家名字。breakonnationselectnation1.nation,nation2.nationborderin_countryfromnationnation1,border,nationnation2wherenation1.code=border.nation_codeandborder.border_code=nation2.codeorderbynation1.nation;---------
--------PL/SQL2PL/SQL的块结构和数据类型块结构的特点嵌套begin......begin......exception......end;exception......end;标识符:不能超过30个字符第一个字符必须为字母其余字符可以是字母,数字,$,_,或#不区分大小写形式如果用双引号括起来,则字符顺序可以任意排列,并区分大小写形式无SQL保留字数据类型数字型:整数,实数,以及指数字符串:用单引号括起来若在字符串表示单引号,则使用两个单引号字符串长度为零(两个单引号之间没有字符),则表示NULL字符:长度为1的字符串数据定义语法标识符[常数]数据类型[NOTNULL][:=PL/SQL表达式];':='表示给变量赋值数据类型包括
数字型字符型日期型布尔型
number(7,2)char(120)dateboolean(取值为true,false或null,不存贮在数据库中)
日期型anniversarydate:='05-JUL-95';project_completiondate;布尔型over_budgetbooleannotnull:=false;availableboolean;(初始值为NULL)%type类型匹配books_printednumber(6);books_soldbook_printed%type;manager_nameemp.ename%type;变量赋值变量名:=PL/SQL表达式numvar:=5;boolvar:=true;datevar:='11-JUN-87';字符型、数字型表达式中的空值null+<数字>=null(空值加数字仍是空值)null><数字>=null(空值与数字进行比较,结果仍是空值)null||'字符串'='字符串'(null即'')(空值与字符串进行连接运算,结果为原字符串)变量作用范围标识符在宣言它的块中有效标识符如果不在子块中重新定义,则在PL/SQL块的所有子块中同样有效重新定义后的标识符,作用范围仅在本子块中有效例declaree_messchar(80);begin/*子块1*/declarev1number(4);begin
selectempnointov1fromempwherejob='president';exceptionwhentoo_many_rowstheninsertintojob_errorsvalues('morethanonepresident');end;/*子块2*/declarev1number(4);beginselectempnointov1fromempwherejob='manager';exceptionwhentoo_many_rowstheninsertintojob_errorsvalues('morethanonemanager');end;exceptionwhenothersthene_mess:=substr(sqlerrm,1,80);insertintogeneralerrorsvalues(e_mess);end;------3SQL和PL/SQL插入declaremy_salnumber(7,2):=3040.55;my_enamechar(25):='wanda';my_hiredatedate:='08-SEP-88';begininsertintoemp(empno,enmae,job,hiredate,sal,deptno)values(2741,my_ename,'cabdriver',my_hiredate,my_sal,20);end;删除declarebad_child_typechar(20):='naughty';begindeletefromsantas_gift_listwherekid_rating=bad_child_type;
end;事务处理commit[WORK];rollback[WORK];(关键字WORK可选,但对命令执行无任何影响)savepoint标记名;(保存当前点)在事务中标记当前点rollback[WORK]to[SAVEPOINT]标记名;(回退到当前保存点)取消savepoint命令之后的所有对数据库的修改关键字WORK和SAVEPOINT为可选项,对命令执行无任何影响函数PL/SQL块中可以使用SQL命令的所有函数insertintophonebook(lastname)value(upper(my_lastname));selectavg(sal)intoavg_salfromemp;对于非SQL命令,可使用大多数个体函数不能使用聚组函数和参数个数不定的函数,如x:=sqrt(y);lastname:=upper(lastname);age_diff:=months_between(birthday1,birthday2)/12;赋值时的数据类型转换4种赋值形式:变量名:=表达式insertinto基表名values(表达式1,表达式2,...);update基表名set列名=表达式;select列名into变量名from...;数据类型间能进行转换的有:char转成numbernumber转成charchar转成datedate转成char例char_var:=nm_var;数字型转换成字符型date_var:='25-DEC-88';字符型转换成日期型insertinto表名(num_col)values('604badnumber');错误,无法成功地转换数据类型
------4条件控制例declarenum_jobsnumber(4);beginselectcount(*)intonum_jobsfromauditionswhereactorid=&;&;actor_idandcalled_back='yes';ifnum_jobs>100thenupdateactorsetactor_rating='wordclass'whereactorid=&;&;actor_id;elsifnum_job=75thenupdateactorsetactor_rating='daytimesoaps'whereactorid=&;&;actor_id;elseupdateactorsetactor_rating='waiter'whereactorid=&;&;actor_id;endif;endif;commit;end;-----5循环语法loop......endloop;exit;(退出循环)exit[when];(退出循环,当满足WHEN时)例1declarectrnumber(3):=0;beginloopinsertintotable1values('tastesgreat');insertintotable2values('lessfilling');ctr:=ctr+1;exitwhenctr=100;endloop;end;(注:如果ctr取为NULL,循环无法结束)例2
FOR语法for变量<范围>loop......endloop;declaremy_indexchar(20):='fettucinialfredo';bowlchar(20);beginformy_indexinreverse21..30loopinsertintotemp(coll)values(my_index);/*循环次数从30到21*/endloop;bowl:=my_index;end;跟在inreverse后面的数字必须是从小到大的顺序,必须是整数,不能是变量或表达式-------6游标显式游标打开游标open<游标名>例opencolor_cur;游标属性%notfound%found%rowcount%isopen例fetchmy_curintomy_var;whilemy_cur%foundloop(处理数据)fetchmy_curintomy_var;exitwhenmy_cur%rowcount=10;endloop;%notfound属性取值情况如下:fetch操作没有返回记录,则取值为truefetch操作返回一条记录,则取值为false对游标无fetch操作时,取值为null
<游标名>%notfound例ifcolor_cur%notfoundthen...注:如果没有fetch操作,则<游标名>%notfound将导致出错,因为%notfound的初始值为NULL。关闭游标close<游标名>例closecolor_cur;游标的FOR循环语法for<记录名>in<游标名>loop<一组命令>endloop;其中:索引是建立在每条记录的值之上的记录名不必声明每个值对应的是记录名,列名初始化游标指打开游标活动集合中的记录自动完成FETCH操作退出循环,关闭游标隐式游标隐式游标是指SQL命令中用到的,没有明确定义的游标insert,update,delete,select语句中不必明确定义游标调用格式为SQL%存贮有关最新一条SQL命令的处理信息隐式游标的属性隐式游标有四个属性SQL%NOTFOUNDSQL%FOUNDSQL%ROWCOUNT:隐式游标包括的记录数例:deletefrombaseball_teamwherebatting_avg<100;ifsql%rowcount>5thninsertintotempvalues('yourteamneedshelp');endif;SQL%ISOPEN:取值总为FALSE。SQL命令执行完毕,PL/SQL立即关闭隐式游标。
7标号GOTO语句用法:gotoyou_are_here;其中you_are_here是要跳转的语句标号标号必须在同一组命令,或是同一块中使用正确的使用<>(标号)x:=x+1ifa>bthenb:=b+c;gotodinner;endif;错误的使用gotojail;ifa>bthenb:=b+c;<>(标号)x:=x+1;endif;标号:解决意义模糊标号可用于定义列值的变量<>declaredeptnonumber:=20;beginupdateempsetsal=sal*1.1wheredeptno=sample.deptno;commit;endsample;如果不用标号和标号限制符,这条命令将修改每条记录。-------8异常处理预定义的异常情况任何ORACLE错误都将自动产生一个异常信息一些异常情况已命名,如:no_data_found当SELECT语句无返回记录时产生too_many_rows没有定义游标,而SELECT语句返回多条记录时产生whenevernotfound无对应的记录
用户定义的异常情况由用户自己获取在DECLARE部分定义:declarexnumber;something_isnt_rightexception;用户定义的异常情况遵循一般的作用范围规则条件满足时,获取异常情况:raisesomething_isnt_right注意:同样可以获取预定义的异常情况exception_init语句允许为ORACLE错误命名调用格式:pragmaexception_init(<表达式>,);例declaredeadlock_detectedexception;pragmaexception_init(deadlock_detected,-60);raise语句单独使用RAISE命令,可再一次获取当前的异常情况(就象异常情况被重复处理了一样)。在异常处理中,此语句只能单独使用。异常处理标识符一组用于处理异常情况的语句:exceptionwhen<表达式>or[表达式...]then<一组语句>...whenothersthen--最后一个处理<一组语句>end;既结束PL/SQL块部分,也结束异常处理部分-----练习与答案1:接收contract_no和item_no值,在inventory表中查找,如果产品:已发货,在arrival_date中赋值为今天后的7天已订货,在arrival_date中赋值为今天后的一个月既无订货又无发货,则在arrival_date中赋值为今天后的两个月,并在order表中增加一条新的订单记录。
product_status的列值为'shipped'和'ordered'inventory:product_idnumber(6)product_descriptionchar(30)product_statuschar(20)std_shipping_qtynumber(3)contract_item:contract_nonumber(12)item_nonumber(6)arrival_datedateorder:order_idnumber(6)product_idnumber(6)qtynumber(3)答案:declarei_product_idinventory.product_id%type;i_product_descriptioninventory.product_description%type;i_product_statusinventory.product_status%type;i_std_shipping_qtyinventory.std_shipping_qty%type;beginselectproduct_id,product_description,product_status,std_shipping_qtyintoi_product_id,i_product_description,i_product_status,i_std_shipping_qtyfrominventorywhereproduct_id=(selectproduct_idfromcontract_itemwherecontract_no=&;&;contractnoanditem_no=&;&;itemno);ifi_product_status='shipped'thenupdatecontract_itemsetarrival_date=sysdate+7whereitem_no=&;&;itemnoandcontract_no=&;&;contractno;elsifi_product_status='ordered'thenupdatecontract_itemsetarrival_date=add_months(sysdate,1)whereitem_no=&;&;itemnoandcontract_no=&;&;contractno;elseupdatecontract_item
setarrival_date=add_months(sysdate,2)whereitem_no=&;&;itemnoandcontract_no=&;&;contractno;insertintoordersvalues(100,i_product_id,i_std_shipping_qty);endif;endif;commit;end;
2:1.找出指定部门中的所有雇员2.用带'&;'的变量提示用户输入部门编号3.把雇员及工资存入prnttable表中,基结构为:createtableprnttable(seqnumber(7),linechar(80));4.异常情况为,部门中奖金不为空值的雇员信息才能存入prnttable表中。答案:declarecursoremp_curisselectename,sal,commfromempwheredeptno=&;dno;emp_recemp_cur%rowtype;null_commissionexception;beginopenemp_cur;fetchemp_curintoemp_rec;while(emp_cur%found)loopifemp_recmisnullthenbegincloseemp_cur;raisenull_commission;end;endif;fetchemp_curintoemp_rec;endloop;closeemp_sur;exceptionwhennull_commissionthenopenemp_cur;fetchemp_curintoemp_rec;while(emp_cur%found)loopifemp_recmisnotnullthen
insertintotempvalues(emp_rec.sal,emp_rec.ename);endif;fetchemp_curintoemp_rec;endloop;closeemp_cur;commit;end