oracle pl/sql语言初级教程之过程和函数
过程和函数
过程和函数都以编译后的形式存放在数据库中,函数可以没有参数也可以有多个参数并有一个返回值。过程有零个或多个参数,没有返回值。函数和过程都可以通过参数列表接收或返回零个或多个值,函数和过程的主要区别不在于返回值,而在于他们的调用方式。过程是作为一个独立执行语句调用的:
pay_involume(invoice_nbr,30,due_date);
函数以合法的表达式的方式调用:
order_volumn:=open_orders(sysdate,30);
创建过程的语法如下:
每个参数的语法如下:
paramter_name mode datatype [(:=|default) value]
mode有三种形式:in、out、inout。
in表示在调用过程的时候,实际参数的取值被传递给该过程,形式参数被认为是只读的,当过程结束时,控制会返回控制环境,实际参数的值不会改变。
out在调用过程时实际参数的取值都将被忽略,在过程内部形式参数只能是被赋值,而不能从中读取数据,在过程结束后形式参数的内容将被赋予实际参数。
inout这种模式是in和out的组合;在过程内部实际参数的值会传递给形式参数,形势参数的值可读也可写,过程结束后,形势参数的值将赋予实际参数。
创建函数的语法和过程的语法基本相同,唯一的区别在于函数有returen子句
在执行部分函数必须有哟个或多个return语句。
在创建函数中可以调用单行函数和组函数,例如:
包
包是一种将过程、函数和数据结构捆绑在一起的容器;包由两个部分组成:外部可视包规范,包括函数头,过程头,和外部可视数据结构;另一部分是包主体(package body),包主体包含了所有被捆绑的过程和函数的声明、执行、异常处理部分。
打包的pl/sql程序和没有打包的有很大的差异,包数据在用户的整个会话期间都一直存在,当用户获得包的执行授权时,就等于获得包规范中的所有程序和数据结构的权限。但不能只对包中的某一个函数或过程进行授权。包可以重载过程和函数,在包内可以用同一个名字声明多个程序,在运行时根据参数的数目和数据类型调用正确的程序。
创建包必须首先创建包规范,创建包规范的语法如下:
创建包主体使用create package body语句:
私有数据结构是那些在包主体内部,对被调用程序而言是不可见的。
触发器(triggers)
触发器是一种自动执行响应数据库变化的程序。可以设置为在触发器事件之前或之后触发或执行。能够触发触发器事件的事件包括下面几种:
dml事件
ddl事件
数据库事件
dml事件触发器可以是语句或行级触发器。dml语句触发器在触发语句之前或之后触发dml行级触发器在语句影响的行变化之前或之后触发。用户可以给单一事件和类型定义多个触发器,但没有任何方法可以增强多触发器触发的命令。下表列出了用户可以利用的触发器事件:
创建触发器的语法如下:
只有dml触发器(insert、update、delete)语句可以使用instead of触发器并且只有表的dml触发器可以是before或after触发器。
象约束一样触发器可以被设置为禁用或启用来关闭或打开他们的执行体(execute),将触发器设置为禁用或启用使用alter trigger语句:
要禁用或启用表的所有触发器,使用alter table语句
删除触发器使用drop trigger
数据字典
oracle数据字典包含了用户数据库的元数据。带下划线的表名称中带obj$、uet$、source$,这些表是在执行create database语句期间由sql.bsq脚本创建的,一般情况下用户很少访问这些表。脚本catalog.sql(通常位于$oracle_home/rdbms/admin)在create database语句之后立即运行,创建数据字典视图。
数据字典视图大致可以分为三类:
.前缀为user_的数据字典视图,包含了用户拥有的对象的信息。
.前缀为all_的数据字典视图,包含了用户当前可以访问的全部对象和权限的信息。
.前缀为dba_的数据字典视图,包含了数据库拥有的所有对象和权限的信息。
在绝大多数数据字典视图中都有象dba_tables,all_tables和user_tables这样的视图家族。oracle中有超过100个视图家族,所以要全面介绍这些视图家族是单调乏味的而且没有多大的意义。在下表中列出了最重要和最常用的视图家族,需要注意的是每个视图家族都有一个dba_,一个all_一个user_视图。
在oracle中还有一些不常用的数据字典表,但这些表不是真正的字典家族,他们都是一些重要的单一的视图。
其他的字典视图中主要的是v$视图,之所以这样叫是因为他们都是以v$或gv$开头的。v$视图是基于x$虚拟视图的。v$视图是sys用户所拥有的,在缺省状况下,只有sys用户和拥有dba系统权限的用户可以看到所有的视图,没有dba权限的用户可以看到user_和all_视图,但不能看到dba_视图。与dba_,all,和user_视图中面向数据库信息相反,这些视图可视的给出了面向实例的信息。
在大型系统上化几周时间手工输入每一条语句
手工输入带用户名变量的语句,然后再输入每一个用户名,这需要花好几个小时的时间
写一条sql语句,生成需要的alter user语句,然后执行他,这只需要几分钟时间
很明显我们将选择生成sql的方法:
例:
这个查询的结果将被脱机处理到一个文件中,然后在执行:
过程和函数都以编译后的形式存放在数据库中,函数可以没有参数也可以有多个参数并有一个返回值。过程有零个或多个参数,没有返回值。函数和过程都可以通过参数列表接收或返回零个或多个值,函数和过程的主要区别不在于返回值,而在于他们的调用方式。过程是作为一个独立执行语句调用的:
pay_involume(invoice_nbr,30,due_date);
函数以合法的表达式的方式调用:
order_volumn:=open_orders(sysdate,30);
创建过程的语法如下:
create [ or replace] procedure [schema.]procedure_name [parameter_lister] {as|is} declaration_section begin executable_section [exception exception_section] end [procedure_name] |
每个参数的语法如下:
paramter_name mode datatype [(:=|default) value]
mode有三种形式:in、out、inout。
in表示在调用过程的时候,实际参数的取值被传递给该过程,形式参数被认为是只读的,当过程结束时,控制会返回控制环境,实际参数的值不会改变。
out在调用过程时实际参数的取值都将被忽略,在过程内部形式参数只能是被赋值,而不能从中读取数据,在过程结束后形式参数的内容将被赋予实际参数。
inout这种模式是in和out的组合;在过程内部实际参数的值会传递给形式参数,形势参数的值可读也可写,过程结束后,形势参数的值将赋予实际参数。
创建函数的语法和过程的语法基本相同,唯一的区别在于函数有returen子句
create [ or replace] finction [schema.]function_name [parameter_list] return returning_datatype {as|is} declaration_section begin executable_section [exception] exception_section end [procedure_name] |
在执行部分函数必须有哟个或多个return语句。
在创建函数中可以调用单行函数和组函数,例如:
create or replace function my_sin(degreesin in number) return number is pi number=acos(-1); radiansperdegree number; begin radiansperdegree=pi/180; return(sin(degreesin*radiansperdegree)); end |
包是一种将过程、函数和数据结构捆绑在一起的容器;包由两个部分组成:外部可视包规范,包括函数头,过程头,和外部可视数据结构;另一部分是包主体(package body),包主体包含了所有被捆绑的过程和函数的声明、执行、异常处理部分。
打包的pl/sql程序和没有打包的有很大的差异,包数据在用户的整个会话期间都一直存在,当用户获得包的执行授权时,就等于获得包规范中的所有程序和数据结构的权限。但不能只对包中的某一个函数或过程进行授权。包可以重载过程和函数,在包内可以用同一个名字声明多个程序,在运行时根据参数的数目和数据类型调用正确的程序。
创建包必须首先创建包规范,创建包规范的语法如下:
create [or replace] package package_name {as|is} public_variable_declarations | public_type_declarations | public_exception_declarations | public_cursor_declarations | function_declarations | procedure_specifications end [package_name] |
创建包主体使用create package body语句:
create [or replace] package body package_name {as|is} private_variable_declarations | private_type_declarations | private_exception_declarations | private_cursor_declarations | function_declarations | procedure_specifications end [package_name] |
私有数据结构是那些在包主体内部,对被调用程序而言是不可见的。
触发器(triggers)
触发器是一种自动执行响应数据库变化的程序。可以设置为在触发器事件之前或之后触发或执行。能够触发触发器事件的事件包括下面几种:
dml事件
ddl事件
数据库事件
dml事件触发器可以是语句或行级触发器。dml语句触发器在触发语句之前或之后触发dml行级触发器在语句影响的行变化之前或之后触发。用户可以给单一事件和类型定义多个触发器,但没有任何方法可以增强多触发器触发的命令。下表列出了用户可以利用的触发器事件:
事件 | 触发器描述 |
insert | 当向表或视图插入一行时触发触发器 |
update | 更新表或视图中的某一行时触发触发器 |
delete | 从表或视图中删除某一行时触发触发器 |
create | 当使用create语句为数据库或项目增加一个对象时触发触发器 |
alter | 当使用alter语句为更改一个数据库或项目的对象时触发触发器 |
drop | 当使用drop语句删除一个数据库或项目的对象时触发触发器 |
start | 打开数据库时触发触发器,在事件后触发 |
shutdown | 关闭数据库时触发,事件前触发 |
logon | 当一个会话建立时触发,事件前触发 |
logoff | 当关闭会话时触发,事件前触发 |
server | 服务器错误发生时触发触发器,事件后触发 |
创建触发器的语法如下:
create [or replace] trigger trigger_name {before|after|instead of} event on {table_or_view_name|database} [for each row[when condition]] trigger_body |
只有dml触发器(insert、update、delete)语句可以使用instead of触发器并且只有表的dml触发器可以是before或after触发器。
象约束一样触发器可以被设置为禁用或启用来关闭或打开他们的执行体(execute),将触发器设置为禁用或启用使用alter trigger语句:
alter trigger trigger_name enable; alter trigger trigger_name disable; |
要禁用或启用表的所有触发器,使用alter table语句
alter trigger table_name disable all trigger; alter trigger table_name enable all trigger; |
删除触发器使用drop trigger
drop trigger trigger_name; |
数据字典
oracle数据字典包含了用户数据库的元数据。带下划线的表名称中带obj$、uet$、source$,这些表是在执行create database语句期间由sql.bsq脚本创建的,一般情况下用户很少访问这些表。脚本catalog.sql(通常位于$oracle_home/rdbms/admin)在create database语句之后立即运行,创建数据字典视图。
数据字典视图大致可以分为三类:
.前缀为user_的数据字典视图,包含了用户拥有的对象的信息。
.前缀为all_的数据字典视图,包含了用户当前可以访问的全部对象和权限的信息。
.前缀为dba_的数据字典视图,包含了数据库拥有的所有对象和权限的信息。
在绝大多数数据字典视图中都有象dba_tables,all_tables和user_tables这样的视图家族。oracle中有超过100个视图家族,所以要全面介绍这些视图家族是单调乏味的而且没有多大的意义。在下表中列出了最重要和最常用的视图家族,需要注意的是每个视图家族都有一个dba_,一个all_一个user_视图。
视图家族(view family) | 描述 |
col_privs | 包含了表的列权限,包括授予者、被授予者和权限 |
extents | 数据范围信息,比如数据文件,数据段名(segment_name)和大小 |
indexes | 索引信息,比如类型、唯一性和被涉及的表 |
ind_columns | 索引列信息,比如索引上的列的排序方式 |
objects | 对象信息,比如状态和ddl time |
role_privs | 角色权限,比如grant和admin选项 |
segments | 表和索引的数据段信息,比如tablespace和storage |
sequecnces | 序列信息,比如序列的cache、cycle和ast_number |
source | 除触发器之外的所有内置过程、函数、包的源代码 |
synonyms | 别名信息,比如引用的对象和数据库链接db_link |
sys_privs | 系统权限,比如grantee、privilege、admin选项 |
tab_columns | 表和视图的列信息,包括列的数据类型 |
tab_privs | 表权限,比如授予者、被授予者和权限 |
tables | 表信息,比如表空间(tablespace),存储参数(storage parms)和数据行的数量 |
triggers | 触发器信息,比如类型、事件、触发体(trigger body) |
users | 用户信息,比如临时的和缺省的表空间 |
views | 视图信息,包括视图定义 |
在oracle中还有一些不常用的数据字典表,但这些表不是真正的字典家族,他们都是一些重要的单一的视图。
view name | 描述 |
user_col_privs_made | 用户授予他人的列权限 |
user_col_privs_recd | 用户获得的列权限 |
user_tab_privs_made | 用户授予他人的表权限 |
user_tab_privs_recd | 用户获得的表权限 |
其他的字典视图中主要的是v$视图,之所以这样叫是因为他们都是以v$或gv$开头的。v$视图是基于x$虚拟视图的。v$视图是sys用户所拥有的,在缺省状况下,只有sys用户和拥有dba系统权限的用户可以看到所有的视图,没有dba权限的用户可以看到user_和all_视图,但不能看到dba_视图。与dba_,all,和user_视图中面向数据库信息相反,这些视图可视的给出了面向实例的信息。
在大型系统上化几周时间手工输入每一条语句
手工输入带用户名变量的语句,然后再输入每一个用户名,这需要花好几个小时的时间
写一条sql语句,生成需要的alter user语句,然后执行他,这只需要几分钟时间
很明显我们将选择生成sql的方法:
例:
select 'alter user'||username|| 'temporary tablespace temp;' from dba_users where username<>'sys' and temporary_tablespace<>'temp'; |
这个查询的结果将被脱机处理到一个文件中,然后在执行:
alter user system temporary tablespace temp; alter user outln temporary tablespace temp; alter user dbsnmp temporary tablespace temp; alter user scott temporary tablespace temp; alter user demo temporary tablespace temp; |