第八章PLSQL.docx

上传人:b****1 文档编号:23171405 上传时间:2023-05-15 格式:DOCX 页数:25 大小:26.45KB
下载 相关 举报
第八章PLSQL.docx_第1页
第1页 / 共25页
第八章PLSQL.docx_第2页
第2页 / 共25页
第八章PLSQL.docx_第3页
第3页 / 共25页
第八章PLSQL.docx_第4页
第4页 / 共25页
第八章PLSQL.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

第八章PLSQL.docx

《第八章PLSQL.docx》由会员分享,可在线阅读,更多相关《第八章PLSQL.docx(25页珍藏版)》请在冰豆网上搜索。

第八章PLSQL.docx

第八章PLSQL

PL/SQL编程

1.概述

什么是PL/SQL?

pl/sql(procedurallanguage/sql)是oracle在标准的sql语言上的扩展.pl/sql不仅允许嵌入sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误,这样使得它的功能变得更加强大

PL/SQL有什么优点?

⏹支持SQL【DML,TCL,游标,函数,运算符,伪列等】

⏹提高应用程序的运行性能

⏹模块化的设计思想【块结构,如存储过程,函数,触发器等】

⏹减少网络传输量

⏹提高安全性

2.PL/SQL体系结构

PL/SQL主要结合了ORACLE的过程语言PL和结构化查询语言SQL,当我们执行PL/SQL块时,请求发送到ORACLE服务器,有PL/SQL引擎来编译和执行PL/SQL块或者子程序,该引擎驻留在Oracle服务器中,其中PL与SQL执行不同分工,过程语句有PL语句执行器执行,SQL语句有SQL语句执行器执行。

3.PL/SQL块

PL/SQL块概述

PL/SQL块指的就是将逻辑上相关的声明和语句组合在一起。

块(block)是pl/sql的基本程序单元,编写pl/sql程序实际上就是编写pl/sql块。

要完成相对简单的应用功能,可能只需要编写一个pl/sql块;但是如果要想实现复杂的功能,可能需要在一个pl/sql块中嵌套其它的pl/sql块

PL/SQL块的分类

根据块的定义和使用,我们可以简单将块分为匿名块和非匿名块,匿名块执行时传入到PL/SQL引擎即可,之前没有定义,非匿名块主要包括过程,函数,触发器,程序包等,事先已经在服务器定义好,可直接根据名称执行。

注意:

在块中不能直接使用DDL语句,但可以通过动态SQL来解决

PL/SQL块的结构

PL/SQL分为三个部分,声明部分、可执行部分和异常处理

⏹声明部分

声明部分包含了变量和常量的数据类型和初始值,由declare开始,如果块中不需要变量和常量,可以忽略声明部分。

⏹可执行部分

执行部分是PL/SQL块中的指令部分,由关键字begin开始,所有可以执行语句都放在这一部分,其他块也可以嵌套在这一部分

⏹异常处理

异常处理部分是可选的,用来处理可以执行部分引发的异常或错误

PL/SQL基础

编写规范

Ø注释

--单行注释

/*块注释*/

Ø标识符的命名规范

1.定义变量:

建议用v_作为前缀v_price

2.定义常量:

建议用c_作为前缀c_pi

3.定义游标:

建议用_cursor作为后缀emp_cursor

4.定义例外:

建议用e_作为前缀e_error

4.PL/SQL编程

✓定义第一个ORACLE程序块,在控制台输出HelloWorld!

--仅包含执行部分的PL/SQL块

begin

dbms_output.put_line('HelloWorld!

');

end;

✓说明:

dbms_output.put_line()是Oracle提供的一个执行输出操作的过程,其中dbms_ouput是包名,put_line()是过程名

✓SETSERVEROUTPUTON:

开启控制台输出选项

✓定义包含定义和执行部分的PL/SQL块

declare

namevarchar2(30);--定义变量name存储姓名

agenumber;--定义变量age存储年龄

sexvarchar2(10)default'男';--定义变量sex存储性别,默认男

minAgeconstantnumber:

=18;--定义常量,存储最小年龄

begin

name:

='zhangSan';

age:

=20;

dbms_output.put_line('姓名:

'||name||',年龄:

'||age||'性别:

'||sex);

dbms_output.put_line('学生最小年龄是:

'||minAge);

end;

注意:

在PL/SQL块中,可执行部分中所有使用的变量必须先声明再使用。

⏹声明变量

Ø语法

变量名数据类型[NOTNULL][:

=|默认值]

例如:

Namevarchar2(30);--定义变量name

Sexvarchar(10)notnulldefault‘男’--notnull必须设置默认值

minAgenumber:

=18–设置默认值

minAgenumberdefault18–设置默认值

Ø为变量赋值

1:

使用赋值运算符赋值

例如:

name:

=’Jack’;

2:

使用selectinto动态赋值

例如:

selectenameintomynamefromempwhereempno=7788;

Selectename,salintomyname,mysalfromempwhereempno=7788

Selectsum(sal)intoallSalfromemp

 

⏹声明常量

Ø语法

常量名Constant数据类型:

=常量值

例如:

minAgeConstantnumber:

=18

⏹PL/SQL的数据类型

每个PL/SQL变量都具有一个指定存储格式,值的有效范围和约束条件的数据类型,PL/SQL提供了各种内置数据类型,包括varchar2,number,date,recode引用类型,大数据类型以及用户自定义类型等。

PL/SQL将这些类型分成了4个大类,分别为:

Ø标量数据类型

ØLOB数据类型

Ø组合【复合】数据类型

Ø引用【参照】数据类型

a)标量数据类型

标量类型是非常常用的一种类型,没有内部组件,仅包含单个值,主要包括number,character,date/time,boolean类型

案例一:

根据用户传入的工号,查询出用户姓名。

declare

namevarchar2(4);

begin

--&代表由用户根据提示手动输入

selectenameintonamefromempwhereempno=&empno;

dbms_output.put_line('姓名为:

'||name);

end;

 

案例二:

如果上面的案例中,查询出的用户姓名长度超过4时会如何,程序将出错,如何解决这种问题?

可以使用%type属性定义变量,这样它会按照数据库列来确定你定义的变量的类型和长度

declare

nameemp.ename%type;

begin

selectenameintonamefromempwhereempno=&empno;

dbms_output.put_line('姓名为:

'||name);

end;

 

emp.ename%type:

和emp表中ename的数据类型,长度一致

案例三:

如果查询返回一个结果集,结果集中列的个数,类型不知道,该如何解决呢?

%RowType:

返回一个记录类型,其数据类型和数据表的数据结构一致

declare

v_noemp.empno%type:

=&empno;

recemp%rowtype;

begin

select*intorecfromempwhereempno=v_no;

dbms_output.put_line('姓名:

'||rec.ename||'工资'||rec.sal);

end;

b)组合数据类型record

用来存储多个值的变量称之为组合或者复合变量,其中存储的多个值可以是PL/SQL记录,也可以是PL/SQL中的表

PL/SQL记录:

类似与高级语言中的结构体,需要注意的是,当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)

案例一:

查询出编号为7788员工的姓名,岗位,工资。

declare

typeemp_mytypeisrecord

nameemp.ename%type,

jobemp.job%type,

salemp.sal%type

);

einfoemp_mytype;

begin

selectename,job,salintoeinfofromempwhereempno=7788;

dbms_output.put_line('姓名:

'||einfo.name||'岗位:

'||einfo.job||'待遇:

'||einfo.sal);

end;

不足:

一次只能存储一条记录的值

c)组合数据类型table

PL/SQL表:

相当于高级语言中的数组.但是需要注意的是在高级语言中数组的下标不能为负数,而pl/sql是可以为负数的,并且表元素的下标没有限制

案例:

查询出部门编号为7788,7900,7902的员工姓名

declare

typemy_tableistableofemp.ename%typeindexbybinary_integer;

einfomy_table;

begin

selectenameintoeinfo

(1)fromempwhereempno=7788;

selectenameintoeinfo

(2)fromempwhereempno=7900;

selectenameintoeinfo(3)fromempwhereempno=7902;

dbms_output.put_line('姓名1:

'||einfo

(1)||'姓名2:

'||einfo

(2)||'姓名3:

'||einfo(3));

end;

注意:

可以使用bulkcollect一次将符合条件的数据全部写入表中

d)引用数据类型

e)LOB数据类型

✓定义包含定义,执行过程和例外处理部分的PL/SQL块

declare

--声明变量

v_namevarchar2(20);

v_salnumber(7,2);

begin

--执行查询,条件中的&表示从控制接受数据

selectename,salintov_name,v_sal

fromempwhereempno=&no;

--控制台输出

dbms_output.put_line('用户名:

'||v_name);

dbms_output.put_line('工资:

'||v_sal);

exception

--例外处理(no_data_found)

whenno_data_foundthen

dbms_output.put_line('执行查询没有结果');

end;

预定义例外

1)case_not_found预定义例外

在开发pl/sql块中编写case语句时,如果在when子句中没有包含必须的条件分支,就会触发case_not_found例外。

2)cursor_already_open预定义例外

当重新打开已经打开的游标时,会隐含的触发cursor_already_open例外。

3)dup_val_on_index预定义例外

在唯一索引所对应的列上插入重复的值时,会隐含的触发例外

4)invalid_cursorn预定义例外

当试图在不合法的游标上执行操作时,会触发该例外

5)invalid_number预定义例外

当输入的数据有误时,会触发该例外

6)no_data_found预定义例外

当执行selectinto没有返回行,就会触发该例外

7)too_many_rows预定义例外

当执行selectinto语句时,如果返回超过了一行,则会触发该例外

8)zero_divide预定义例外

当执行2/0语句时,则会触发该例外

9)value_error预定义例外

当在执行赋值操作时,如果变量的长度不足以容纳实际数据,则会触发该例外value_error

5.PL/SQL控制语句

✓条件分支语句

if—then

declare

--声明变量

v_empnoemp.empno%type;

v_salemp.sal%type;

begin

--根据雇员编号查询工资

selectempno,salintov_empno,v_salfromempwhereempno=&no;

--如果工资小于2000就加100

ifv_sal<2000

then

--工资加100

updateempsetsal=sal+100whereempno=v_empno;

--提交

commit;

endif;

end;

if—then—else

declare

--声明变量

v_loginnamevarchar2(10);

v_passwordvarchar2(10);

begin

--从控制台接收数据

v_loginname:

='&ln';

v_password:

='&pw';

ifv_loginname='admin'andv_password='123456'

then

dbms_output.put_line('用户登录成功!

');

else

dbms_output.put_line('用户登录失败!

');

endif;

end;

if—then—elsif—else

declare

--声明变量

v_empnoemp.empno%type;

v_jobemp.job%type;

begin

--根据雇员编号查询职位

selectempno,jobintov_empno,v_jobfromempwhereempno=&no;

/*如果雇员所属职位是manager工资加1000

职位是salesman工资加500

其他职位加200

*/

ifv_job='MANAGER'then

--MANAGER职位工资加1000

updateempsetsal=sal+1000whereempno=v_empno;

elsifv_job='SALESMAN'then

--SALESMAN职位工资加500

updateempsetsal=sal+500whereempno=v_empno;

else

--其他职位工资加200

updateempsetsal=sal+200whereempno=v_empno;

endif;

--提交

commit;

end;

case

declare

--声明变量

v_marknumber(4);

v_outstrvarchar2(40);

begin

--从控制台接收成绩

v_mark:

=&m;

case

whenv_mark<=100andv_mark>=90then

v_outstr:

='优秀';

whenv_mark<90andv_mark>=80then

v_outstr:

='良好';

whenv_mark<80andv_mark>=70then

v_outstr:

='中等';

whenv_mark<70andv_mark>=60then

v_outstr:

='及格';

whenv_mark<60andv_mark>=0then

v_outstr:

='不及格';

else

v_outstr:

='成绩输入有误';

endcase;

--控制台输出

dbms_output.put_line(v_outstr);

end;

✓循环语句

1)loop

LOOP要执行的语句;

EXITWHEN<条件语句>/*条件满足,退出循环语句*/

ENDLOOP;

其中:

EXITWHEN子句是必须的,否则循环将无法停止。

declare

v_numnumber(4):

=1;

begin

--从控制台接收数据并插入到account表中

loop

insertintoaccountvalues(v_num,'&name');

exitwhenv_num=10;

v_num:

=v_num+1;

endloop;

end;

2)while

WHILE<布尔表达式>LOOP要执行的语句;ENDLOOP;

其中:

✓循环语句执行的顺序是先判断<布尔表达式>的真假,如果为真则循环执行,否则退出循环

✓在WHILE循环语句中仍然可以使用EXIT或EXITWHEN子句

declare

v_numnumber(4):

=1;

begin

--从控制台接收数据并插入到account表中

whilev_num<11

loop

insertintoaccountvalues(v_num,'&name');

v_num:

=v_num+1;

endloop;

end;

--处理复杂问题也可以使用嵌套循环,如下,打印九九乘法表

declare

v_iint:

=1;

v_jint:

=1;

begin

whilev_i<=9

loop

v_j:

=1;--每行都从第一列开始打印

whilev_j<=v_i

loop

dbms_output.put(v_j||'*'||v_i||'='||v_i*v_j||'');

v_j:

=v_j+1;

endloop;

v_i:

=v_i+1;

dbms_output.put_line('');--打印换行

endloop;

end;

3)for

FOR循环计数器IN[REVERSE]下限..上限LOOP要执行的语句;ENDLOOP;

其中:

✓每循环一次,循环变量自动加1;使用关键字REVERSE,循环变量自动减1

✓跟在INREVERSE后面的数字必须是从小到大的顺序,但不一定是整数,可以是能够转换成整数的变量或表达式

✓可以使用EXITWHEN子句退出循环

--输出1到10的数

begin

foriin1..10

loop

--控制台输出

dbms_output.put_line(i);

endloop;

end;

--输出一组数据

declare

--声明表类型

typeemp_table_typeistableofvarchar2(20)

indexbyPLS_INTEGER;--表示表按整数来排序

v_enamesemp_table_type;--定义变量引用表类型

begin

--所有值赋予v_enames

selectenamebulkcollectintov_enamesfromemp;

--输出

foriin1..v_enames.count

loop

dbms_output.put_line(v_enames(i));

endloop;

end;

--记录类型可以和表类型结合使用

--定义一个表类型,要求存储所有的员工姓名和工资

declare

--声明记录类型

typeemp_typeisrecord

v_nameemp.ename%type,--存储姓名

v_salemp.sal%type--存储工资

);

--声明表类型

typeemp_table_typeistableofemp_type

indexbyPLS_INTEGER;--表示表按整数来排序

v_infosemp_table_type;--定义变量引用表类型

begin

--所有值赋予v_enames

selectename,salbulkcollectintov_infosfromemp;

--输出

foriin1..v_infos.count

loop

dbms_output.put_line('姓名'||v_infos(i).v_name||',工资'||v_infos(i).v_sal);

endloop;

end;

6.动态SQL

在PL/SQL块中,可以执行DML和TCL,但是不可以直接执行DDL以及DCL,如果想在块中使用,必须使用动态SQL

ORACLE的编译程序块方式有2种,分别是:

1)前期联编

SQL语句在程序编译期间就以及确定,大多数的编译情况属于这种类型,也称为静态SQL语句

2)后期联编

SQL语句只有在运行阶段才建立并执行,也称为动态SQL语句

Oracle中动态SQL可以通过本地动态SQL来执行,也可以通过DBMS_SQL包来执行

 

Ø本地动态执行SQL语法:

Executeimmediatedynamic_sql_string

[intodefine_variable_list]

[usingbind_argument_list]

说明:

dynamic_sql_string:

动态SQL语句

define_variable_list:

用于接受select查询记录值的变量列表

bind_argument_list:

绑定输入参数的列表

案例一:

本地动态SQL执行DDL语句

Declare

table_namevarchar2(50):

='&table_name';

str_sqlvarchar2(500);

v_countint;

begin

--查询表中是否有记录

str_sql:

='selectcount(*)from'||table_name;

--执行动态语句,并将结果赋值给变量v_count

executeimmediatestr_sqlintov_count;

ifv_count>0then

dbms_output.put_line('表中有数据,不能删除!

');

else

--构建动态DDL语句

str_sql:

='droptable'||table_name||'purge';

executeimmediatestr_sql;

dbms_output.put_line('表已经删除!

');

commit;

endif;

end;

案例二:

本地执行DML语句

Declare

empnovarchar2(50):

='7902';

str_sqlvarchar2(500);

begin

str_sql:

='deleteempwhereempno=:

1';

--动态执行DML语句,并赋予动态参数值

executeimmediatestr_sqlusingempno;

co

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

当前位置:首页 > 外语学习 > 其它语言学习

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

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