20个案例掌握PL SQL 基础.docx

上传人:b****3 文档编号:3483993 上传时间:2022-11-23 格式:DOCX 页数:21 大小:57.99KB
下载 相关 举报
20个案例掌握PL SQL 基础.docx_第1页
第1页 / 共21页
20个案例掌握PL SQL 基础.docx_第2页
第2页 / 共21页
20个案例掌握PL SQL 基础.docx_第3页
第3页 / 共21页
20个案例掌握PL SQL 基础.docx_第4页
第4页 / 共21页
20个案例掌握PL SQL 基础.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

20个案例掌握PL SQL 基础.docx

《20个案例掌握PL SQL 基础.docx》由会员分享,可在线阅读,更多相关《20个案例掌握PL SQL 基础.docx(21页珍藏版)》请在冰豆网上搜索。

20个案例掌握PL SQL 基础.docx

20个案例掌握PLSQL基础

20个案例掌握PL/SQL基础

       有MSSQL基础,学习了两周多的PL/SQL,做了一些事例,但是很多信息在网上难以找到太多正确的答案,看到一篇又一篇的PL/SQL博文,案例方面的博文一篇又一篇的雷同,一看就是是Ctrl+C的复制.给一些博主留言希望得到解答,但是等到却是"我也是复制来的,具体的没测试".

       狠心之下,花了不少时间学习.做了一些例子,搞定之余,留下点供参考的例子.

       阅读本篇博文之前,建议你学习一下基础,这是推荐的两个PL/SQL博客,

EricHu胡勇:

Oracle编程详解       =>传送门

liulun:

    PL/SQL学习笔记(索引帖)=>传送门 

 

测试:

SQLNavigator3+Oracle;远程连接

用以下案例来总结PL/SQL相关知识:

1.将2010-12-06转换成Dec-06-2010的格式.

错解:

1selectto_char(to_date('2010-12-06','yyyy-mm-dd'),'mon-dd-yyyy')fromdual

PS:

如果安装的系统默认语言为EN,那么这种执行结果正确,但是若是CN那就错了.所以,需要设置一下显示的语言才能保证Dec的出现.

正解:

1selectto_char(to_date('2010-12-06','yyyy-mm-dd'),'mon-dd-yyyy','NLS_DATE_LANGUAGE=American')fromdual

2.PL/SQL中常用round函数,trunc函数,instr函数,substr函数的区别.

正解:

(1)round(x,y)以小数点右边第y位四舍五入x;

(2)trunc(x,y)舍去小数点右边第y位以后的数字;

(不要去看网上的所谓负数出现的解释,没什么用,以后出现的机会也不会存在)

(3)instr(str1,str2,num)

        Str1:

原字符串,str2要查找的字符串,num第几次出现

        返回要查找的str2在原字符串str1中第num次出现的位置,若不存在,则返回0;

(4)substr(str1,num1,num2)截取字符串str中从num1位开始之后的num2个,num1为负数时反向

3.外连接与内连接:

正解:

oracle外连接中左.右.全连接的区别=> 传送门

4.如何删除重复的记录.

错解:

1select*from表whereIdin(selectIdfrom表groupbyIdhavingcount(Id)>1)

PS:

仔细看了一下代码,自己居然粗心地把所有重复记录数据的都按id删除了,但是是不是该保留一行呢?

!

正解:

1deletefromtable

2whereidin

3(

4selectidfromtable

5groupbyid

6havingcount(id)>1

7androwidnotin

8(

9selectmin(rowid)fromtable

10--记住oracle中独有的标识列字段rowid,

11--查询所有重复id但是不包括最小(min)的id,删除之;最大的效果同理.

12--但是是不是还有个问题,id必须是递增而且是设为主键的,要不然,这道例子......

13)

14)

5.返回今天星期几(5.1返回星期五;5,2返回Friday)

正解:

5.1

1selectto_char(sysdate,'day','nls_date_language=''simplifiedchinese''')fromdual

5.2

1selectto_char(sysdate,'day','nls_date_language=American')fromdual

PS:

这个和和第一题类似.注意5.1的simplifiedchinese后面的3个单引号,因为是字符串.所以在

simplifiedchinese要加上单引号'simplifiedchinese',但是因为两个单词中间有空格,再加上一层

''simplifiedchinese'',再有一个单引号就是转义符,变成了''simplifiedchinese'''.反正有点混乱,看我在论坛问的这个解答:

      

6.返回当前月的最后一天.

 正解:

1selectlast_day(add_months(sysdate,0))fromdual

PS:

如果把sysydate加法或者减法,结果就是求出加法或者减法之后的月份的最后一天

7.使用Oracle自带函数实现输入5.5,分别得到6和5;

正解:

1selectround(5.5,0)fromdual--得到6

2selecttrunc(5.5,0)fromdual--得到5

PS:

参看第2题已有解释.

8.给现有日期加上2年.

正解:

1selectadd_months(sysdate,24)fromdual

PS:

天真的以为add_years存在,试了试,居然没有这个函数.

9. 搜索出users表中工号以s开头的,前10条记录.

错解:

select*fromuserswhereidlike'S*'andrownum<=10

PS:

没有*吧,以前在Windows系统中搜索文件常用*?

等,结果现在忘了是在写PL/SQL.惯例,rownum是Oracle特有.

正解:

1select*fromuserswhereidlike'S%'andrownum<=10

10.插入全年日期进入mgs_psd_report表F1栏.

正解:

测试表test4,类似mgs_psd_report表.

创建test4表语句(我在这里创建test4以备语句测试,实际上一样,不要拘泥于具体的表名):

1--(实验表test4

2select*fromtest4

3droptabletest4

4createtabletest4

5(

6F1number,

7F2varchar(20),

8F3number

9)

10--)

插入语句(mgs_psd_report):

1--存储过程.以前存储过程真是没怎么写过,现在补习虽然说有点不习惯.不过还好,基本格式对了,居然写出来了.

2createorreplaceprocedureSp_ShowDate(v_yearinvarchar2)

3as

4v_datecountnumber:

=0;--从0开始,因为要算上第一天

5v_datelengthnumber;

6v_datestartdate;--第一天

7v_dateenddate;--最后一天

8begin

9--selectto_char(sysdate,'yyyy')||'0101'intov_datestartfromdual

10selectto_date((v_year||'0101'),'yyyymmdd')intov_datestartfromdual;--第一天

11selectto_date((v_year||'1231'),'yyyymmdd')intov_dateendfromdual;--最后一天

12

13selectv_dateend-v_datestartintov_datelengthfromdual;--不加1,因为第一天加上364或者365相当于365或者366天

14

15whilev_datecount<=v_datelengthloop

16insertintomgs_psd_report(F1)values(to_char(to_date(to_char(v_year||'0101'),'yyyymmdd')+v_datecount,'yyyymmdd'));

17v_datecount:

=v_datecount+1;

18endloop;

19end;

20--执行.以'2012'年为例

21begin

22Sp_ShowDate('2012');

23end;

PS:

居然还真对了,蛮高兴的.

11.写一个存储过程,更新上一题中的F2栏位(可以见我上题创建的test4表语句),更新所有的.

要求:

若当天星期六.星期日为N;

     5月1日到5月3日,10月1日到10月3日为N2;

     其他日期为P.

错解就不贴了,有点长.

正解:

1--创建

2createorreplaceprocedureSp_UpdateDate(v_yearinvarchar2)--年份

3as

4v_datecountnumber:

=0;--从0开始,因为要算上第一天

5v_datelengthnumber;--总天数

6v_datestartdate;--第一天

7v_dateenddate;--最后一天

8v_datetempvarchar2(20);--日期

9v_datetemp2varchar(20);--星期几

10begin

11selectto_date((v_year||'0101'),'yyyymmdd')intov_datestartfromdual;--第一天

12selectto_date((v_year||'1231'),'yyyymmdd')intov_dateendfromdual;--最后一天

13selectv_dateend-v_datestartintov_datelengthfromdual;--不加1,因为第一天加上364或者365相当于365或者366天

14

15whilev_datecount<=v_datelengthloop

16selectF1intov_datetempfrommgs_psd_reportwhereF1=to_char(to_date(to_char(v_year||'0101'),'yyyymmdd')+v_datecount,'yyyymmdd');

17selectto_char(to_date(trim(v_datetemp),'yyyymmdd'),'day','nls_date_language=American')intov_datetemp2fromdual;

18iftrim(v_datetemp2)='saturday'ortrim(v_datetemp2)='sunday'then

19updatemgs_psd_reportsetF2='N'whereF1=v_datetemp;

20else

21iftrim(v_datetemp)=(v_year||'0501')ortrim(v_datetemp)=(v_year||'0502')ortrim(v_datetemp)=(v_year||'0503')ortrim(v_datetemp)=(v_year||'1001')ortrim(v_datetemp)=(v_year||'1002')ortrim(v_datetemp)=(v_year||'1003')then

22updatemgs_psd_reportsetF2='n2'whereF1=v_datetemp;

23else

24updatemgs_psd_reportsetF2='P'whereF1=v_datetemp;

25endif;

26endif;

27v_datecount:

=v_datecount+1;

28endloop;

29endSp_UpdateDate;

30

31--执行

32begin

33Sp_UpdateDate('2012');

34end;

效果图:

 12.如何快速清空一个大表(不要清空db中现有数据)

错解:

1deletefrom表名--可以回滚

PS:

快速!

具体的...这个没实践,看书得到的结果.

正解:

1truncatetable表名--不可以回滚,速度更快

13.写一个函数可以进行16进制和10进制的转换.

正解:

10=>16

1--函数

2createorreplacefunctionfun_10to16(v_numinnumber)

3returnvarchar2

4as

5v_tempvarchar2(20);

6begin

7selectto_char(v_num,'xxxxx')intov_tempfromdual;

8returnv_temp;

9endfun_10to16;

10--执行

11declare

12v_testnumber:

=16;

13v_tempvarchar(20):

='';

14begin

15v_temp:

=fun_10to16(v_test);

16dbms_output.put_line(v_temp);

17end;

18selectfun_10to16(16)fromdual

16=>10

1--函数

2createorreplacefunctionfun_16to10(v_numinvarchar2)

3returnvarchar2

4as

5v_tempvarchar2(20);

6begin

7selectto_number(v_num,'xxxxx')intov_tempfromdual;

8returnv_temp;

9endfun_16to10;

10--执行

11selectfun_16to10(‘1E’)fromdual

PS:

这个没多大难度,但是不能忘了function的写法步骤.

 14.编写一个函数,实现加减乘除,要求有异常处理.

正解:

1createorreplacefunctionfun_getresult(v_num1innumber,v_num2innumber,v_symbolinvarchar2)

2returnnumber

3as

4ex_errorexception;

5v_tempnumber;

6begin

7ifv_symbol='+'then

8v_temp:

=v_num1+v_num2;

9returnv_temp;

10endif;

11ifv_symbol='-'then

12v_temp:

=v_num1-v_num2;

13returnv_temp;

14endif;

15ifv_symbol='*'then

16v_temp:

=v_num1*v_num2;

17returnv_temp;

18endif;

19ifv_symbol='/'then

20ifv_num2=0then

21raiseex_error;

22else

23v_temp:

=v_num1/v_num2;

24returnv_temp;

25endif;

26endif;

27exception

28whenex_errorthen

29dbms_output.put_line('ocannotbeusedhere!

');

30end;

31

32--执行

33selectfun_getresult(12,3,'/')fromdual

PS:

开始写的时候没有异常处理,只用了if判断被除数是否为0,这个就不算是异常处理了.

15.写一个触发器,操作一个表(emp_info)时,向另一个表(emp_info_bk)插入操作的内容.测试向其插入 "'" ,"|"字符。

 正解:

1--创建

2createorreplacetriggertr_replace

3beforeinsertorupdateordelete

4onemp_info

5foreachrow

6begin

7insertintoemp_info_bkvalues(:

new.creator,:

new.creation_date,:

new.id,:

new.name,:

new.address);

8endtr_replace;

9--执行

10insertintoemp_infovalues(23,'test22','test22',to_date('20130426','yyyymmdd'),'dong2')

11insertintoemp_infovalues(24,'''','|',to_date('20130426','yyyymmdd'),'dong3')

PS:

触发器,写的更少了,诶.

  --select'''||'fromdual

||正常引到引号中,就是字符了。

而单引号,需要前边再加一个单引号转义。

''''四个单引号,前后两个表示字符串两端的单引号,中间部分是字符串。

而中间有两个单引号,第一个是转义字符,表示把第二个转成字符串的单引号。

第二个,就是外围两个单引号引住的实际的字符串的单引号。

 16.用一条sql实现以下转换

studentsubjectgrade

---------------------------

student1语文80

student1数学70

student1英语60

student2语文90

student2数学80

student2英语100

......

转换为:

      语文数学英语

student1807060

student29080100

正解:

selectstudent姓名,sum(decode(subject,'语文',grade,null))语文,sum(decode(subject,'数学',grade,null))数学,sum(decode(subject,'英语',grade,null))英语

fromteststu

groupbystudent

PS:

decode用法,要注意了.

17.调用sen_email过程把某个数据发送到xx@

正解:

createorreplaceprocedureSp_SendMyEmail(v_Frominvarchar2,v_Toinvarchar2,v_Subjectinvarchar2,v_Bodyinvarchar2)

as

v_CcVARCHAR2(20):

=NULL;

v_BccVARCHAR2(20):

=NULL;

v_ContentTypeVARCHAR2(40):

='text/plain;charset=gb2312';

v_MailIpVARCHAR2(20):

=这里是服务器的IP地址xx.xxx.xx.x';

v_PortNUMBER:

=25;

begin

send_email(v_From,v_To,v_Subject,v_Body,v_Cc,v_Bcc,v_ContentType,v_MailIp,v_Port);

endSp_SendMyEmail;

--执行

begin

Sp_SendMyEmail(2,'xx@','test1','111111*********11111111111111111');

end;

PS:

提示错误:

ORA-29278:

SMTPtransienterror:

421Servicenotavailable.说明这个写的正确,另外想问一点:

如果

   v_CcVARCHAR2(20):

=NULL;

   v_BccVARCHAR2(20):

=NULL;

   v_ContentTypeVARCHAR2(40):

='text/plain;charset=gb2312';

   v_MailIpVARCHAR2(20):

='xx.xxx.x.x';

   v_PortNUMBER:

=25;

 在存储过程中已经初始化了,但是存储过程传递的参数中还有这些变量,难道必须得我这么做,在外面调用时候还得初始化一下?

不然怎么传参?

求解.

18.列出总分成绩处于第5位的学生;另写一个sql语句得到大于或者等于80的为优秀,大于或者等于60的为及格,小于60分显示不及格

Stu        数学   语文   化学

student1    50     100   99

student2    80     60    100

student3    60     70    20

student4    90     80    80

student5    100    67    85

student6    100    77    81

...

正解:

select*from(

selectrownumid,stufrom(

selectstu,sum(yw+sx+hx)result

fromtest3

groupbystu

orderbyresultasc

whereid='5'

--因为数据中没有rownum这个列,不能直接写出rownum=5这样的查询,所以为了可以使用rownum,不断查询,把rownum保存入id用来

1selectstu,

2casewhensx<60then'不及格'else(casewhensx>80then'优秀'else'及格'end)endassx,

3casewhenyw<60then'不及格'else(casewhenyw>80then'优秀'else'及格'end)endasyw,

4casewhenhx<60then'不及格'else(casewhenhx>80then'优秀'else'及格'end)end

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1