- 浏览: 2177302 次
文章分类
最新评论
oracle 11g PL/SQL Programming学习十五
第14章 对象类型(Object Types)
面向对象(Object-oriented)编程方案解决了函数、存储、包的一些缺点.
对象类型定义了如何存储数据以及API操作,像成员函数或存储.
操作在面向对象的编程语言中一般描述为方法,但在PL/SQL中实现为类成员函数或存储.
对象类型和对象在很多面向对象的程序语言中也被称为类.
对象类型的定义类似PL/SQL的包头和包体,对象类型体实现了对象类型定义的内容,包体实现了包头的内容.
可以像SQL数据类型一样创建对象类型及对象类型体.
你可以在以下4种情况中使用对象类型:
1.可以用做表列的数据类型
2.可以作为对象属性的数据类型
3.可以作为存储或函数的参数的数据类型
4.作为函数的返回类型
oracle 11g限定对象要么是永久对象,要么是临时对象.
永久对象又分单独对象和嵌入式对象.
单独对象存储在数据库的表中,有一个唯一的对象标识符.
嵌入式对象不存储在数据库表中,它是嵌入在另外的oracle结构中,像嵌入到另一个对象类型中.
嵌入式对象没有对象标识符.
临时对象是对象的实例,它不存储在数据库中.
临时对象的生命周期受PL/SQL块限制.
这章我们主要学习的是临时对象.
对象的基本内容
1.对象类型命名
必须以字母开头,只能由字母、数字、下划线组成.
对象类型名和其他所有对象共享同一个命名空间,除了数据库触发器对象.
2.对象类型的作用域范围
对象类型的作用域范围和其他函数或存储一样.它们都受到模式(schema)的限制.
当你要在另一个模式中使用对象的时候,你必须要给这个模式授予执行该对象的权限.
对象的声明
PL/SQL对象类型,和包一样,有一个定义原型.
不同的是对象类型有一组专用的函数:CONSTRUCTOR, MAP,ORDER.
构造(CONSTRUCTOR)函数决定了你如何构建对象类型的实例.它返回一个对象类型的实例,在PL/SQL中就是SELF.
你不能像包变量那样声明对象类型变量.
你需要按以下顺序列出对象类型的各个元素:属性、构造函数、函数、存储、MAP或ORDER函数.
对象类型原型:
CREATE [OR REPLACE] OBJECT TYPE object_name
[AUTHID {DEFINER | CURRENT_USER}] IS OBJECT
( [instance_variables {sql_datatype | plsql_datatype}]
, [CONSTRUCTOR FUNCTION constructor_name
[( parameter_list )] RETURN RESULT AS SELF
, [{MEMBER | STATIC} FUNCTION function_name
[( parameter_list )] RETURN { sql_data_type | plsql_data_type }
, [{MEMBER | STATIC} PROCEDURE procedure_name
[( parameter_list)]
,{[MAP FUNCTION map_name RETURN { CHAR | DATE | NUMBER | VARCHAR2 } |
[ORDER FUNCTION order_name RETURN { sql_data_type | plsql_data_type }}])
[NOT] INSTANTIABLE [NOT] FINAL;
如:
对象类型体的实现
和包体一样,对象体的实现必须要和对象中声明的一致.
对象类型体创建原型:
CREATE [OR REPLACE] OBJECT TYPE object_name
[AUTHID {DEFINER | CURRENT_USER}] IS
( [CONSTRUCTOR FUNCTION constructor_name
[( parameter_list )] RETURN RESULT AS SELF IS
BEGIN
execution_statements;
END [constructor_name];
[{MEMBER | STATIC} FUNCTION function_name
[( parameter_list )] RETURN { sql_data_type | plsql_data_type } IS
BEGIN
execution_statements;
END [function_name];
[{MEMBER | STATIC} PROCEDURE procedure_name IS
[( parameter_list)]
BEGIN
execution_statements;
END [procedure_name];
{[MAP FUNCTION map_name RETURN { CHAR | DATE | NUMBER | VARCHAR2 } IS
BEGIN
execution_statements;
END [procedure_name]; |
[ORDER FUNCTION order_name RETURN { sql_data_type | plsql_data_type } IS
BEGIN
execution_statements;
END [procedure_name];}])
END [object_name];
如:
对象类型一般会提供一个缺省的构造函数.缺省的构造函数通常没有参数.
对象类型属性的静态成员方法
静态方法能创建对象类型的实例.
注意静态方法的实现需要创建一个对象类型实例.
静态函数get_item_object使用参数和本地游标从表中寻找到满足条件的行来实例化对象类型.
它返回本地实例化变量.
对象的比对
对象实例的比较在面向编程中是非常重要的.
oracle提供了两个预定义函数MAP和ORDER来完成对象的比较.
你在对象类型体中只能定义MAP和ORDER其中之一.
如果你要同时定义MAP和ORDER在一个对象类型中,你将获得错误PLS-00154.
MAP成员函数不用带参数,只能返回CHAR,DATE,NUMBER,VARCHAR2数据类型.
注:子类不能重写父类的MAP和ORDER函数.
ORDER成员函数就比较复杂,它能带任何SQL数据类型的参数.但它只返回NUMBER数据类型.
使用MAP成员函数比较对象
当对象类型是由单个属性值来实例化的时候,使用MAP函数会很好.
使用ORDER成员函数比较对象
ORDER成员函数允许你传递一个实例对象到另一个对象,来比较它们是否相等.
ORDER成员函数支持多个属性值的对象类型实例的比较.
继承与多态(Inheritance and Polymorphism)
对象是可扩展的,因为你可以通过建立子类来增加它的属性.
子类继承父类的行为,子类也能通过创建父类同名的成员方法来重写父类的行为.
多态就是多个子类继承父类行为的过程.
一个经典的案例就是广义的车辆类.
你可以通过建造汽车、摩托车、卡车、行李车等来开发指定的车类.
这些子类扩展了车辆类的一般属性和方法,甚至有时重写了部分方法.
这些方法使得子类之间有所区别,如开汽车方法和骑摩托车方法.
当车辆类成为子类的时候,交通工具类就成为父类了.
继承又分为单继承和多继承.像JAVA就支持单继承,而C++就支持多继承.
PL/SQL只支持单继承模型,不过你可以使用面向对象的聚合原理来克服这种限制.
子类的声明
UNDER关键字表明当前类为某个类的子类.
子类型的应用有一些限制.
1.你不能重写类型的属性,也就是当你声明子类型时,不能列出它们.
2.MAP和ORDER成员函数是参数列表的元素.这个只用在对象类型中.
当父类已经存在MAP或ORDER函数的时候,你尝试在子类再放一个MAP或ORDER函数,将会获得PLS-00154错误.
如:创建order_comp的子类order_subcomp
注意上面的子类构造函数继承了父类order_comp的两个属性who和movie,并重写了to_string方法.
重写的成员函数to_string中出现了一个新的语法:(self as order_comp).to_string
这个语法让你调用父类的方法.这里调用了父类的to_string方法.
你不能在子类中直接访问父类的属性.
这里子类实例被添加到基类的集合变量中,并做为实参传送到了ORDER成员函数和局部的swap存储中.
子类可在运行时进行隐式转换,此时就和临时对象类型一样.
如:
这里同时插入了一个子类对象和一个父类对象到表中.插入时子类隐式转换为父类.
通过SELECT可以看到列标题显示为父类对象的构造函数,查询的结果,
一行调用了子类的构造函数,另一行存储了调用父类的构造函数.
你可以通过TREAT函数来查询对象内容.
如:
TREAT函数实际是构造了一个子类或父类的实例.你在表列中声明的类型应当总是父类.
如果你在表中声明了一个子类类型的列,插入时会报错.
类型的进化
当数据库永久对象已经存储数据的时候,更改对象类型是需要非常谨慎的.
如果必须要更改的话,你需要一个迁移策略,从旧的永久对象类型迁移到新的.
一旦你声明某对象类型作为表的列类型后,你不能改变该对象类型.
当子类存在数据库的时候,你给父类增加属性,将会获得ORA-02303错误.
如:
对象集合体的实现
实现一个对象类型的集合是比较容易的.
你可以声明一个以该对象类型为元素类型的VARRAY或者嵌套表.
集合的wrapper应该定义至少一个实例变量.这个石磊变量应该是集合数据类型.
items_object构造函数使用一个静态函数get_items_table作为它的实际参数.
静态函数get_items_table返回了集合类型变量items_table.
其中每个元素都是item_object类型的.
面向对象(Object-oriented)编程方案解决了函数、存储、包的一些缺点.
对象类型定义了如何存储数据以及API操作,像成员函数或存储.
操作在面向对象的编程语言中一般描述为方法,但在PL/SQL中实现为类成员函数或存储.
对象类型和对象在很多面向对象的程序语言中也被称为类.
对象类型的定义类似PL/SQL的包头和包体,对象类型体实现了对象类型定义的内容,包体实现了包头的内容.
可以像SQL数据类型一样创建对象类型及对象类型体.
你可以在以下4种情况中使用对象类型:
1.可以用做表列的数据类型
2.可以作为对象属性的数据类型
3.可以作为存储或函数的参数的数据类型
4.作为函数的返回类型
oracle 11g限定对象要么是永久对象,要么是临时对象.
永久对象又分单独对象和嵌入式对象.
单独对象存储在数据库的表中,有一个唯一的对象标识符.
嵌入式对象不存储在数据库表中,它是嵌入在另外的oracle结构中,像嵌入到另一个对象类型中.
嵌入式对象没有对象标识符.
临时对象是对象的实例,它不存储在数据库中.
临时对象的生命周期受PL/SQL块限制.
这章我们主要学习的是临时对象.
对象的基本内容
1.对象类型命名
必须以字母开头,只能由字母、数字、下划线组成.
对象类型名和其他所有对象共享同一个命名空间,除了数据库触发器对象.
2.对象类型的作用域范围
对象类型的作用域范围和其他函数或存储一样.它们都受到模式(schema)的限制.
当你要在另一个模式中使用对象的时候,你必须要给这个模式授予执行该对象的权限.
对象的声明
PL/SQL对象类型,和包一样,有一个定义原型.
不同的是对象类型有一组专用的函数:CONSTRUCTOR, MAP,ORDER.
构造(CONSTRUCTOR)函数决定了你如何构建对象类型的实例.它返回一个对象类型的实例,在PL/SQL中就是SELF.
你不能像包变量那样声明对象类型变量.
你需要按以下顺序列出对象类型的各个元素:属性、构造函数、函数、存储、MAP或ORDER函数.
对象类型原型:
CREATE [OR REPLACE] OBJECT TYPE object_name
[AUTHID {DEFINER | CURRENT_USER}] IS OBJECT
( [instance_variables {sql_datatype | plsql_datatype}]
, [CONSTRUCTOR FUNCTION constructor_name
[( parameter_list )] RETURN RESULT AS SELF
, [{MEMBER | STATIC} FUNCTION function_name
[( parameter_list )] RETURN { sql_data_type | plsql_data_type }
, [{MEMBER | STATIC} PROCEDURE procedure_name
[( parameter_list)]
,{[MAP FUNCTION map_name RETURN { CHAR | DATE | NUMBER | VARCHAR2 } |
[ORDER FUNCTION order_name RETURN { sql_data_type | plsql_data_type }}])
[NOT] INSTANTIABLE [NOT] FINAL;
如:
23:15:27 SCOTT@orcl> create or replace type hello_there is object 23:18:50 2 ( 23:18:50 3 who varchar2(20), 23:18:50 4 constructor function hello_there RETURN SELF AS RESULT, 23:18:50 5 CONSTRUCTOR FUNCTION hello_there(who varchar2) return self as result, 23:18:50 6 member procedure to_string 23:18:50 7 ) 23:18:50 8 instantiable not final; 23:18:53 9 / Type created. Elapsed: 00:00:00.36 23:18:56 SCOTT@orcl> desc hello_there hello_there is NOT FINAL Name Null? Type ----------------------------------------------------- -------- ------------------ WHO VARCHAR2(20) METHOD ------ FINAL CONSTRUCTOR FUNCTION HELLO_THERE RETURNS SELF AS RESULT METHOD ------ FINAL CONSTRUCTOR FUNCTION HELLO_THERE RETURNS SELF AS RESULT Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- WHO VARCHAR2 IN MEMBER PROCEDURE TO_STRING
对象类型体的实现
和包体一样,对象体的实现必须要和对象中声明的一致.
对象类型体创建原型:
CREATE [OR REPLACE] OBJECT TYPE object_name
[AUTHID {DEFINER | CURRENT_USER}] IS
( [CONSTRUCTOR FUNCTION constructor_name
[( parameter_list )] RETURN RESULT AS SELF IS
BEGIN
execution_statements;
END [constructor_name];
[{MEMBER | STATIC} FUNCTION function_name
[( parameter_list )] RETURN { sql_data_type | plsql_data_type } IS
BEGIN
execution_statements;
END [function_name];
[{MEMBER | STATIC} PROCEDURE procedure_name IS
[( parameter_list)]
BEGIN
execution_statements;
END [procedure_name];
{[MAP FUNCTION map_name RETURN { CHAR | DATE | NUMBER | VARCHAR2 } IS
BEGIN
execution_statements;
END [procedure_name]; |
[ORDER FUNCTION order_name RETURN { sql_data_type | plsql_data_type } IS
BEGIN
execution_statements;
END [procedure_name];}])
END [object_name];
如:
23:31:04 SCOTT@orcl> create or replace type body hello_there is 23:34:39 2 constructor function hello_there RETURN SELF AS RESULT is 23:34:39 3 hello hello_there := hello_there('默认构造对象'); 23:34:39 4 begin 23:34:39 5 self := hello; 23:34:39 6 return; 23:34:39 7 end hello_there; 23:34:39 8 CONSTRUCTOR FUNCTION hello_there(who varchar2) return self as result is 23:34:39 9 begin 23:34:39 10 self.who := who; 23:34:39 11 return; 23:34:39 12 end hello_there; 23:34:39 13 member procedure to_string is 23:34:39 14 begin 23:34:39 15 dbms_output.put_line('Hello' || self.who || '.'); 23:34:39 16 end to_string; 23:34:39 17 end; 23:34:40 18 / Type body created. Elapsed: 00:00:00.05
对象类型一般会提供一个缺省的构造函数.缺省的构造函数通常没有参数.
--使用缺省构造函数的对象类型变量 23:34:42 SCOTT@orcl> declare 23:37:22 2 hello hello_there:=hello_there; 23:37:43 3 BEGIN 23:37:45 4 hello.to_string(); 23:37:58 5 END; 23:38:01 6 / Hello默认构造对象. PL/SQL procedure successfully completed. Elapsed: 00:00:00.06 --给定参数的构造函数的对象类型变量 23:38:03 SCOTT@orcl> declare 23:39:30 2 hello hello_there:=hello_there('自定义对象'); 23:40:07 3 BEGIN 23:40:14 4 hello.to_string(); 23:40:15 5 END; 23:40:16 6 / Hello自定义对象. PL/SQL procedure successfully completed. Elapsed: 00:00:00.01
对象类型属性的静态成员方法
静态方法能创建对象类型的实例.
--声明一个含静态方法的对象类型 23:40:17 SCOTT@orcl> create or replace type item_object is object 23:47:26 2 ( 23:47:26 3 item_title varchar2(60), 23:47:26 4 item_subtitle varchar2(60), 23:47:26 5 constructor function item_object RETURN SELF AS RESULT, 23:47:26 6 CONSTRUCTOR FUNCTION item_object(item_title varchar2,item_subtitle varchar2) return self as result, 23:47:27 7 static function get_item_object(item_id number) return item_object, 23:47:27 8 member function to_string return varchar2 23:47:27 9 ) 23:47:27 10 instantiable not final; 23:47:27 11 / Type created. Elapsed: 00:00:00.18
注意静态方法的实现需要创建一个对象类型实例.
--item_object实现 23:56:53 SCOTT@orcl> create or replace type body item_object is 23:58:50 2 constructor function item_object RETURN SELF AS RESULT is 23:58:50 3 item item_object := item_object('默认主标题','默认副标题'); 23:58:50 4 begin 23:58:50 5 self := item; 23:58:50 6 return; 23:58:50 7 end item_object; 23:58:50 8 CONSTRUCTOR FUNCTION item_object(item_title varchar2,item_subtitle varchar2) return self as result is 23:58:50 9 begin 23:58:50 10 self.item_title := item_title; 23:58:50 11 self.item_subtitle:=item_subtitle; 23:58:50 12 return; 23:58:50 13 end item_object; 23:58:50 14 STATIC FUNCTION get_item_object(item_id number) return item_object is 23:58:50 15 item item_object; 23:58:50 16 cursor c(item_id_id number) is 23:58:50 17 select '主&'||ename item_title,'副&'||sal item_subtitle from emp where empno=item_id_id; 23:58:50 18 begin 23:58:50 19 for i in c(item_id) loop 23:58:50 20 item:=item_object(i.item_title,i.item_subtitle); 23:58:50 21 end loop; 23:58:50 22 return item; 23:58:50 23 end get_item_object; 23:58:50 24 member function to_string return varchar2 is 23:58:50 25 begin 23:58:50 26 return '['||self.item_title||']['||self.item_subtitle||']'; 23:58:50 27 end to_string; 23:58:50 28 end; 23:58:50 29 / Type body created. Elapsed: 00:00:00.06
静态函数get_item_object使用参数和本地游标从表中寻找到满足条件的行来实例化对象类型.
它返回本地实例化变量.
--对象类型中的静态函数使用 23:58:51 SCOTT@orcl> begin 00:02:34 2 dbms_output.put_line(item_object.get_item_object(7788).to_string); 00:03:20 3 end; 00:03:24 4 / [主&SCOTT][副&3000] PL/SQL procedure successfully completed. Elapsed: 00:00:00.01
对象的比对
对象实例的比较在面向编程中是非常重要的.
oracle提供了两个预定义函数MAP和ORDER来完成对象的比较.
你在对象类型体中只能定义MAP和ORDER其中之一.
如果你要同时定义MAP和ORDER在一个对象类型中,你将获得错误PLS-00154.
MAP成员函数不用带参数,只能返回CHAR,DATE,NUMBER,VARCHAR2数据类型.
注:子类不能重写父类的MAP和ORDER函数.
ORDER成员函数就比较复杂,它能带任何SQL数据类型的参数.但它只返回NUMBER数据类型.
使用MAP成员函数比较对象
当对象类型是由单个属性值来实例化的时候,使用MAP函数会很好.
--使用MAP来实现简单的冒泡排序算法 00:03:25 SCOTT@orcl> create or replace type map_comp is object 00:14:44 2 ( 00:14:44 3 who varchar2(60), 00:14:44 4 constructor function map_comp(who varchar2) RETURN SELF AS RESULT, 00:14:44 5 map member function equals return varchar2 00:14:44 6 ) 00:14:44 7 instantiable not final; 00:14:46 8 / Type created. Elapsed: 00:00:00.12 00:14:47 SCOTT@orcl> create or replace type body map_comp is 00:17:25 2 constructor function map_comp(who varchar2) RETURN SELF AS RESULT is 00:17:25 3 begin 00:17:25 4 self.who := who; 00:17:25 5 return; 00:17:25 6 end map_comp; 00:17:25 7 map member function equals return varchar2 is 00:17:25 8 begin 00:17:25 9 return self.who; 00:17:25 10 end equals; 00:17:25 11 end; 00:17:27 12 / Type body created. Elapsed: 00:00:00.08 00:22:21 SCOTT@orcl> DECLARE 00:22:51 2 -- Declare a collection of an object type. 00:22:51 3 TYPE object_list IS TABLE OF MAP_COMP; 00:22:51 4 -- Initialize four objects in mixed alphabetical order. 00:22:51 5 object1 MAP_COMP := map_comp('3Ron Weasley'); 00:22:51 6 object2 MAP_COMP := map_comp('2Harry Potter'); 00:22:51 7 object3 MAP_COMP := map_comp('5Luna Lovegood'); 00:22:51 8 object4 MAP_COMP := map_comp('1Hermione Granger'); 00:22:51 9 -- Define a collection of the object type. 00:22:51 10 objects OBJECT_LIST := object_list(object1,object2,object3,object4); 00:22:51 11 -- Swaps A and B. 00:22:51 12 PROCEDURE swap(a IN OUT MAP_COMP,b IN OUT MAP_COMP) IS 00:22:51 13 c MAP_COMP; 00:22:51 14 BEGIN 00:22:51 15 c := b; 00:22:51 16 b := a; 00:22:51 17 a := c; 00:22:51 18 END swap; 00:22:51 19 BEGIN 00:22:51 20 -- Print reordered objects. 00:22:51 21 FOR i IN 1 .. objects.COUNT LOOP 00:22:51 22 dbms_output.put_line('排序前:'||objects(i).equals); 00:22:51 23 END LOOP; 00:22:51 24 dbms_output.put_line('------'); 00:22:51 25 --冒泡排序. 00:22:51 26 FOR i IN 1 .. objects.COUNT LOOP 00:22:51 27 FOR j IN 1 .. objects.COUNT LOOP 00:22:51 28 IF objects(i).equals = LEAST(objects(i).equals, objects(j).equals) THEN 00:22:51 29 swap(objects(i), objects(j)); 00:22:51 30 END IF; 00:22:51 31 END LOOP; 00:22:51 32 END LOOP; 00:22:51 33 -- Print reordered objects. 00:22:51 34 FOR i IN 1 .. objects.COUNT LOOP 00:22:51 35 dbms_output.put_line('排序后:'||objects(i).equals); 00:22:51 36 END LOOP; 00:22:51 37 END; 00:22:51 38 / 排序前:3Ron Weasley 排序前:2Harry Potter 排序前:5Luna Lovegood 排序前:1Hermione Granger ------ 排序后:1Hermione Granger 排序后:2Harry Potter 排序后:3Ron Weasley 排序后:5Luna Lovegood PL/SQL procedure successfully completed. Elapsed: 00:00:00.02
使用ORDER成员函数比较对象
ORDER成员函数允许你传递一个实例对象到另一个对象,来比较它们是否相等.
ORDER成员函数支持多个属性值的对象类型实例的比较.
--使用ORDER函数来实现简单的冒泡排序算法 00:33:52 SCOTT@orcl> create or replace type order_comp is object 00:34:06 2 ( 00:34:06 3 who varchar2(60), 00:34:06 4 movie varchar2(60), 00:34:06 5 constructor function order_comp(who varchar2,movie varchar2) RETURN SELF AS RESULT, 00:34:06 6 member function to_string return varchar2, 00:34:06 7 order member function equals(object order_comp)return number 00:34:06 8 ) 00:34:06 9 instantiable not final; 00:34:06 10 / Type created. Elapsed: 00:00:00.09 00:44:25 SCOTT@orcl> create or replace type body order_comp is 00:45:48 2 constructor function order_comp(who varchar2,movie varchar2) RETURN SELF AS RESULT is 00:45:48 3 begin 00:45:48 4 self.who := who; 00:45:48 5 self.movie := movie; 00:45:48 6 return; 00:45:48 7 end order_comp; 00:45:48 8 member function to_string return varchar2 is 00:45:48 9 begin 00:45:48 10 RETURN '['||self.movie||']['||self.who||']'; 00:45:48 11 end to_string; 00:45:48 12 order member function equals(object order_comp) return number is 00:45:48 13 begin 00:45:48 14 -- The primary sort. 00:45:48 15 IF self.movie < object.movie THEN 00:45:48 16 RETURN 1; 00:45:48 17 -- The secondary sort. 00:45:48 18 ELSIF self.movie = object.movie AND self.who < object.who THEN 00:45:48 19 RETURN 1; 00:45:48 20 ELSE 00:45:48 21 RETURN 0; 00:45:48 22 END IF; 00:45:48 23 end equals; 00:45:48 24 end; 00:45:48 25 / Type body created. Elapsed: 00:00:00.07 00:45:50 SCOTT@orcl> DECLARE 00:49:34 2 -- Declare a collection of an object type. 00:49:34 3 TYPE object_list IS TABLE OF ORDER_COMP; 00:49:34 4 -- Initialize four objects in mixed alphabetical order. 00:49:34 5 object1 ORDER_COMP := order_comp('Ron Weasley', 'Harry Potter 1'); 00:49:34 6 object2 ORDER_COMP := order_comp('Harry Potter', 'Harry Potter 1'); 00:49:34 7 object3 ORDER_COMP := order_comp('Luna Lovegood', 'Harry Potter5'); 00:49:34 8 object4 ORDER_COMP := order_comp('Hermione Granger', 'Harry Potter 1'); 00:49:34 9 object5 ORDER_COMP := order_comp('Hermione Granger', 'Harry Potter 2'); 00:49:34 10 object6 ORDER_COMP := order_comp('Harry Potter', 'Harry Potter 5'); 00:49:34 11 object7 ORDER_COMP := order_comp('Cedric Diggory', 'Harry Potter 4'); 00:49:34 12 object8 ORDER_COMP := order_comp('Severus Snape', 'Harry Potter1'); 00:49:34 13 -- Define a collection of the object type. 00:49:34 14 objects OBJECT_LIST := object_list(object1, 00:49:34 15 object2, 00:49:34 16 object3, 00:49:34 17 object4, 00:49:34 18 object5, 00:49:34 19 object6, 00:49:34 20 object7, 00:49:34 21 object8); 00:49:34 22 -- Swaps A and B. 00:49:34 23 PROCEDURE swap(a IN OUT ORDER_COMP, b IN OUT ORDER_COMP) IS 00:49:34 24 c ORDER_COMP; 00:49:34 25 BEGIN 00:49:34 26 c := b; 00:49:34 27 b := a; 00:49:34 28 a := c; 00:49:34 29 END swap; 00:49:34 30 BEGIN 00:49:34 31 FOR i IN 1 .. objects.COUNT LOOP 00:49:34 32 dbms_output.put_line('排序前:' || objects(i).to_string); 00:49:34 33 END LOOP; 00:49:34 34 dbms_output.put_line('------'); 00:49:34 35 --冒泡排序 00:49:34 36 FOR i IN 1 .. objects.COUNT LOOP 00:49:34 37 FOR j IN 1 .. objects.COUNT LOOP 00:49:34 38 IF objects(i).equals(objects(j)) = 1 THEN 00:49:34 39 -- 升序排列 00:49:34 40 swap(objects(i), objects(j)); 00:49:34 41 END IF; 00:49:34 42 END LOOP; 00:49:34 43 END LOOP; 00:49:34 44 -- Print reordered objects. 00:49:34 45 FOR i IN 1 .. objects.COUNT LOOP 00:49:34 46 dbms_output.put_line('排序后:' || objects(i).to_string); 00:49:34 47 END LOOP; 00:49:34 48 END; 00:49:34 49 / 排序前:[Harry Potter 1][Ron Weasley] 排序前:[Harry Potter 1][Harry Potter] 排序前:[Harry Potter 5][Luna Lovegood] 排序前:[Harry Potter 1][Hermione Granger] 排序前:[Harry Potter 2][Hermione Granger] 排序前:[Harry Potter 5][Harry Potter] 排序前:[Harry Potter 4][Cedric Diggory] 排序前:[Harry Potter 1][Severus Snape] ------ 排序后:[Harry Potter 1][Harry Potter] 排序后:[Harry Potter 1][Hermione Granger] 排序后:[Harry Potter 1][Ron Weasley] 排序后:[Harry Potter 1][Severus Snape] 排序后:[Harry Potter 2][Hermione Granger] 排序后:[Harry Potter 4][Cedric Diggory] 排序后:[Harry Potter 5][Harry Potter] 排序后:[Harry Potter 5][Luna Lovegood] PL/SQL procedure successfully completed. Elapsed: 00:00:00.02 00:49:36 SCOTT@orcl> DECLARE 00:52:54 2 -- Declare a collection of an object type. 00:52:54 3 TYPE object_list IS TABLE OF ORDER_COMP; 00:52:54 4 -- Initialize four objects in mixed alphabetical order. 00:52:54 5 object1 ORDER_COMP := order_comp('Ron Weasley', 'Harry Potter 1'); 00:52:54 6 object2 ORDER_COMP := order_comp('Harry Potter', 'Harry Potter 1'); 00:52:54 7 object3 ORDER_COMP := order_comp('Luna Lovegood', 'Harry Potter5'); 00:52:54 8 object4 ORDER_COMP := order_comp('Hermione Granger', 'Harry Potter 1'); 00:52:54 9 object5 ORDER_COMP := order_comp('Hermione Granger', 'Harry Potter 2'); 00:52:54 10 object6 ORDER_COMP := order_comp('Harry Potter', 'Harry Potter 5'); 00:52:54 11 object7 ORDER_COMP := order_comp('Cedric Diggory', 'Harry Potter 4'); 00:52:54 12 object8 ORDER_COMP := order_comp('Severus Snape', 'Harry Potter1'); 00:52:54 13 -- Define a collection of the object type. 00:52:54 14 objects OBJECT_LIST := object_list(object1, 00:52:54 15 object2, 00:52:54 16 object3, 00:52:54 17 object4, 00:52:54 18 object5, 00:52:54 19 object6, 00:52:54 20 object7, 00:52:54 21 object8); 00:52:54 22 -- Swaps A and B. 00:52:54 23 PROCEDURE swap(a IN OUT ORDER_COMP, b IN OUT ORDER_COMP) IS 00:52:54 24 c ORDER_COMP; 00:52:54 25 BEGIN 00:52:54 26 c := b; 00:52:54 27 b := a; 00:52:54 28 a := c; 00:52:54 29 END swap; 00:52:54 30 BEGIN 00:52:54 31 FOR i IN 1 .. objects.COUNT LOOP 00:52:54 32 dbms_output.put_line('排序前:' || objects(i).to_string); 00:52:54 33 END LOOP; 00:52:54 34 dbms_output.put_line('------'); 00:52:54 35 --冒泡排序 00:52:54 36 FOR i IN 1 .. objects.COUNT LOOP 00:52:54 37 FOR j IN 1 .. objects.COUNT LOOP 00:52:54 38 IF objects(i).equals(objects(j)) = 0 THEN 00:52:54 39 --降序排列 00:52:54 40 swap(objects(i), objects(j)); 00:52:54 41 END IF; 00:52:54 42 END LOOP; 00:52:54 43 END LOOP; 00:52:54 44 -- Print reordered objects. 00:52:54 45 FOR i IN 1 .. objects.COUNT LOOP 00:52:54 46 dbms_output.put_line('排序后:' || objects(i).to_string); 00:52:54 47 END LOOP; 00:52:54 48 END; 00:52:54 49 / 排序前:[Harry Potter 1][Ron Weasley] 排序前:[Harry Potter 1][Harry Potter] 排序前:[Harry Potter 5][Luna Lovegood] 排序前:[Harry Potter 1][Hermione Granger] 排序前:[Harry Potter 2][Hermione Granger] 排序前:[Harry Potter 5][Harry Potter] 排序前:[Harry Potter 4][Cedric Diggory] 排序前:[Harry Potter 1][Severus Snape] ------ 排序后:[Harry Potter 5][Luna Lovegood] 排序后:[Harry Potter 5][Harry Potter] 排序后:[Harry Potter 4][Cedric Diggory] 排序后:[Harry Potter 2][Hermione Granger] 排序后:[Harry Potter 1][Severus Snape] 排序后:[Harry Potter 1][Ron Weasley] 排序后:[Harry Potter 1][Hermione Granger] 排序后:[Harry Potter 1][Harry Potter] PL/SQL procedure successfully completed. Elapsed: 00:00:00.04
继承与多态(Inheritance and Polymorphism)
对象是可扩展的,因为你可以通过建立子类来增加它的属性.
子类继承父类的行为,子类也能通过创建父类同名的成员方法来重写父类的行为.
多态就是多个子类继承父类行为的过程.
一个经典的案例就是广义的车辆类.
你可以通过建造汽车、摩托车、卡车、行李车等来开发指定的车类.
这些子类扩展了车辆类的一般属性和方法,甚至有时重写了部分方法.
这些方法使得子类之间有所区别,如开汽车方法和骑摩托车方法.
当车辆类成为子类的时候,交通工具类就成为父类了.
继承又分为单继承和多继承.像JAVA就支持单继承,而C++就支持多继承.
PL/SQL只支持单继承模型,不过你可以使用面向对象的聚合原理来克服这种限制.
子类的声明
UNDER关键字表明当前类为某个类的子类.
子类型的应用有一些限制.
1.你不能重写类型的属性,也就是当你声明子类型时,不能列出它们.
2.MAP和ORDER成员函数是参数列表的元素.这个只用在对象类型中.
当父类已经存在MAP或ORDER函数的时候,你尝试在子类再放一个MAP或ORDER函数,将会获得PLS-00154错误.
如:创建order_comp的子类order_subcomp
22:47:12 SCOTT@orcl> create or replace type order_subcomp UNDER order_comp 22:50:48 2 ( 22:50:48 3 subtitle varchar2(20), 22:50:48 4 constructor function order_subcomp(who varchar2, 22:50:48 5 movie varchar2, 22:50:48 6 subtitle varchar2) 22:50:48 7 return self as result, 22:50:48 8 overriding member function to_string return varchar2 22:50:48 9 ) 22:50:48 10 instantiable final; 22:50:49 11 / Type created. Elapsed: 00:00:00.22
注意上面的子类构造函数继承了父类order_comp的两个属性who和movie,并重写了to_string方法.
--子类对象类型体的实现 22:50:51 SCOTT@orcl> CREATE OR REPLACE TYPE BODY order_subcomp IS 22:54:32 2 CONSTRUCTOR FUNCTION order_subcomp(who VARCHAR2, 22:54:32 3 movie VARCHAR2, 22:54:32 4 subtitle VARCHAR2) RETURN SELF AS RESULT IS 22:54:32 5 BEGIN 22:54:32 6 self.who := who; 22:54:32 7 self.movie := movie; 22:54:32 8 self.subtitle := subtitle; 22:54:32 9 RETURN; 22:54:32 10 END order_subcomp; 22:54:32 11 OVERRIDING MEMBER FUNCTION to_string RETURN VARCHAR2 IS 22:54:32 12 BEGIN 22:54:32 13 RETURN(self as order_comp).to_string || '[' || self.subtitle || ']'; 22:54:32 14 END to_string; 22:54:32 15 END; 22:54:34 16 / Type body created. Elapsed: 00:00:00.14
重写的成员函数to_string中出现了一个新的语法:(self as order_comp).to_string
这个语法让你调用父类的方法.这里调用了父类的to_string方法.
你不能在子类中直接访问父类的属性.
--子类对象类型的使用 23:00:06 SCOTT@orcl> DECLARE 23:00:29 2 -- Declare a collection of an object type. 23:00:29 3 TYPE object_list IS TABLE OF ORDER_COMP; 23:00:29 4 -- Initialize one subtype. 23:00:29 5 object1 ORDER_SUBCOMP := order_subcomp('Ron Weasley', 23:00:29 6 'Harry Potter 1', 23:00:29 7 'Socerer''s Stone'); 23:00:29 8 -- Initialize seven types. 23:00:29 9 object2 ORDER_COMP := order_comp('Harry Potter', 'Harry Potter 1'); 23:00:29 10 object3 ORDER_COMP := order_comp('Luna Lovegood', 'Harry Potter5'); 23:00:29 11 object4 ORDER_COMP := order_comp('Hermione Granger', 'Harry Potter 1'); 23:00:29 12 object5 ORDER_COMP := order_comp('Hermione Granger', 'Harry Potter 2'); 23:00:29 13 object6 ORDER_COMP := order_comp('Harry Potter', 'Harry Potter 5'); 23:00:29 14 object7 ORDER_COMP := order_comp('Cedric Diggory', 'Harry Potter 4'); 23:00:29 15 object8 ORDER_COMP := order_comp('Severus Snape', 'Harry Potter1'); 23:00:29 16 -- Define a collection of the object type. 23:00:29 17 objects OBJECT_LIST := object_list(object1, 23:00:29 18 object2, 23:00:29 19 object3, 23:00:29 20 object4, 23:00:29 21 object5, 23:00:29 22 object6, 23:00:29 23 object7, 23:00:29 24 object8); 23:00:29 25 -- Swaps A and B. 23:00:29 26 PROCEDURE swap(a IN OUT ORDER_COMP, b IN OUT ORDER_COMP) IS 23:00:29 27 c ORDER_COMP; 23:00:29 28 BEGIN 23:00:29 29 c := b; 23:00:29 30 b := a; 23:00:29 31 a := c; 23:00:29 32 END swap; 23:00:29 33 BEGIN 23:00:29 34 FOR i IN 1 .. objects.COUNT LOOP 23:00:29 35 dbms_output.put_line('排序前:'||objects(i).to_string); 23:00:29 36 END LOOP; 23:00:29 37 dbms_output.put_line('-----------'); 23:00:29 38 -- A bubble sort. 23:00:29 39 FOR i IN 1 .. objects.COUNT LOOP 23:00:29 40 FOR j IN 1 .. objects.COUNT LOOP 23:00:29 41 IF objects(i).equals(objects(j)) = 1 THEN 23:00:29 42 swap(objects(i), objects(j)); 23:00:29 43 END IF; 23:00:29 44 END LOOP; 23:00:29 45 END LOOP; 23:00:29 46 -- Print reordered objects. 23:00:29 47 FOR i IN 1 .. objects.COUNT LOOP 23:00:29 48 dbms_output.put_line('排序后:'||objects(i).to_string); 23:00:29 49 END LOOP; 23:00:29 50 END; 23:00:29 51 / 排序前:[Harry Potter 1][Ron Weasley][Socerer's Stone] 排序前:[Harry Potter 1][Harry Potter] 排序前:[Harry Potter 5][Luna Lovegood] 排序前:[Harry Potter 1][Hermione Granger] 排序前:[Harry Potter 2][Hermione Granger] 排序前:[Harry Potter 5][Harry Potter] 排序前:[Harry Potter 4][Cedric Diggory] 排序前:[Harry Potter 1][Severus Snape] ----------- 排序后:[Harry Potter 1][Harry Potter] 排序后:[Harry Potter 1][Hermione Granger] 排序后:[Harry Potter 1][Ron Weasley][Socerer's Stone] 排序后:[Harry Potter 1][Severus Snape] 排序后:[Harry Potter 2][Hermione Granger] 排序后:[Harry Potter 4][Cedric Diggory] 排序后:[Harry Potter 5][Harry Potter] 排序后:[Harry Potter 5][Luna Lovegood] PL/SQL procedure successfully completed. Elapsed: 00:00:00.04
这里子类实例被添加到基类的集合变量中,并做为实参传送到了ORDER成员函数和局部的swap存储中.
子类可在运行时进行隐式转换,此时就和临时对象类型一样.
如:
23:00:32 SCOTT@orcl> CREATE TABLE harry_potter 23:06:45 2 ( harry_potter_id NUMBER 23:06:45 3 , character_role ORDER_COMP ); Table created. Elapsed: 00:00:00.40 23:06:46 SCOTT@orcl> INSERT INTO harry_potter 23:07:25 2 VALUES(1, order_subcomp('Ron Weasley', 'Harry Potter 1', 'Socerer''s Stone')); 1 row created. Elapsed: 00:00:00.09 23:07:25 SCOTT@orcl> INSERT INTO harry_potter 23:07:25 2 VALUES(1, order_comp('Hermione Granger', 'Harry Potter 1')); 1 row created. Elapsed: 00:00:00.00 23:08:52 SCOTT@orcl> SELECT character_role FROM harry_potter; CHARACTER_ROLE(WHO, MOVIE) ----------------------------------------------------------------- ORDER_SUBCOMP('Ron Weasley', 'Harry Potter 1', 'Socerer''s Stone') ORDER_COMP('Hermione Granger', 'Harry Potter 1') 2 rows selected. Elapsed: 00:00:00.16
这里同时插入了一个子类对象和一个父类对象到表中.插入时子类隐式转换为父类.
通过SELECT可以看到列标题显示为父类对象的构造函数,查询的结果,
一行调用了子类的构造函数,另一行存储了调用父类的构造函数.
你可以通过TREAT函数来查询对象内容.
如:
23:09:01 SCOTT@orcl> SELECT TREAT(character_role AS ORDER_COMP).to_string() AS character_role 23:13:25 2 FROM harry_potter; CHARACTER_ROLE ------------------------------------------------------------ [Harry Potter 1][Ron Weasley][Socerer's Stone] [Harry Potter 1][Hermione Granger] 2 rows selected. Elapsed: 00:00:00.02
TREAT函数实际是构造了一个子类或父类的实例.你在表列中声明的类型应当总是父类.
如果你在表中声明了一个子类类型的列,插入时会报错.
23:16:56 SCOTT@orcl> CREATE TABLE sub_harry_potter 23:17:23 2 ( harry_potter_id NUMBER 23:17:23 3 , character_role ORDER_subCOMP ); Table created. Elapsed: 00:00:00.06 23:17:24 SCOTT@orcl> INSERT INTO sub_harry_potter 23:18:40 2 VALUES(1, order_subcomp('Hermione Granger', 'Harry Potter 1')); VALUES(1, order_subcomp('Hermione Granger', 'Harry Potter 1')) * ERROR at line 2: ORA-06553: PLS-306: wrong number or types of arguments in call to 'ORDER_SUBCOMP ' Elapsed: 00:00:00.01 23:18:40 SCOTT@orcl> INSERT INTO sub_harry_potter 23:18:40 2 VALUES(1, order_subcomp('Ron Weasley', 'Harry Potter 1', 'Socerer' 's Stone')); 1 row created. Elapsed: 00:00:00.01 23:18:56 SCOTT@orcl> INSERT INTO sub_harry_potter 23:19:32 2 VALUES(1, order_comp('Hermione Granger', 'Harry Potter 1')); VALUES(1, order_comp('Hermione Granger', 'Harry Potter 1')) * ERROR at line 2: ORA-00932: inconsistent datatypes: expected SCOTT.ORDER_SUBCOMP got SCOTT.ORDER_COMP Elapsed: 00:00:00.01
类型的进化
当数据库永久对象已经存储数据的时候,更改对象类型是需要非常谨慎的.
如果必须要更改的话,你需要一个迁移策略,从旧的永久对象类型迁移到新的.
一旦你声明某对象类型作为表的列类型后,你不能改变该对象类型.
当子类存在数据库的时候,你给父类增加属性,将会获得ORA-02303错误.
如:
23:21:21 SCOTT@orcl> create or replace type order_comp is object 23:29:20 2 ( 23:29:20 3 who varchar2(60), 23:29:20 4 movie varchar2(60), 23:29:20 5 addtest varchar2(60), 23:29:20 6 constructor function order_comp(who varchar2,movie varchar2,addtest VARCHAR2) RETURN SELF AS RESULT, 23:29:20 7 member function to_string return varchar2, 23:29:20 8 order member function equals(object order_comp)return number 23:29:20 9 ) 23:29:20 10 instantiable not final; 23:29:21 11 / create or replace type order_comp is object * ERROR at line 1: ORA-02303: cannot drop or replace a type with type or table dependents Elapsed: 00:00:00.03
对象集合体的实现
实现一个对象类型的集合是比较容易的.
你可以声明一个以该对象类型为元素类型的VARRAY或者嵌套表.
--创建item_object类型的集合类型(嵌套表) 23:29:22 SCOTT@orcl> CREATE OR REPLACE TYPE item_table IS TABLE OF item_object; 23:32:17 2 / Type created. Elapsed: 00:00:00.20
集合的wrapper应该定义至少一个实例变量.这个石磊变量应该是集合数据类型.
--ITEM_TABLE集合类型的使用 23:32:19 SCOTT@orcl> CREATE OR REPLACE TYPE items_object IS OBJECT 23:35:51 2 ( 23:35:51 3 items_table ITEM_TABLE, 23:35:51 4 CONSTRUCTOR FUNCTION items_object RETURN SELF AS RESULT, 23:35:51 5 CONSTRUCTOR FUNCTION items_object(items_table ITEM_TABLE) 23:35:51 6 RETURN SELF AS RESULT, 23:35:51 7 MEMBER FUNCTION get_size RETURN NUMBER, 23:35:51 8 STATIC FUNCTION get_items_table RETURN ITEM_TABLE 23:35:51 9 ) 23:35:51 10 INSTANTIABLE NOT FINAL; 23:35:52 11 / Type created. Elapsed: 00:00:00.07 23:35:54 SCOTT@orcl> CREATE OR REPLACE TYPE BODY items_object IS 23:39:39 2 CONSTRUCTOR FUNCTION items_object RETURN SELF AS RESULT IS 23:39:39 3 c NUMBER := 1; -- Counter for table index. 23:39:39 4 item ITEM_OBJECT; 23:39:39 5 CURSOR c1 IS 23:39:39 6 SELECT ename, job FROM emp; 23:39:39 7 BEGIN 23:39:39 8 FOR i IN c1 LOOP 23:39:39 9 item := item_object(i.ename, i.job); 23:39:39 10 items_table.EXTEND; 23:39:39 11 self.items_table(c) := item; -- Must use something other than loop index. 23:39:39 12 c := c + 1; 23:39:39 13 END LOOP; 23:39:39 14 RETURN; 23:39:39 15 END items_object; 23:39:39 16 CONSTRUCTOR FUNCTION items_object(items_table ITEM_TABLE) 23:39:39 17 RETURN SELF AS RESULT IS 23:39:39 18 BEGIN 23:39:39 19 self.items_table := items_table; 23:39:39 20 RETURN; 23:39:39 21 END items_object; 23:39:39 22 MEMBER FUNCTION get_size RETURN NUMBER IS 23:39:39 23 BEGIN 23:39:39 24 RETURN self.items_table.COUNT; 23:39:39 25 END get_size; 23:39:39 26 STATIC FUNCTION get_items_table RETURN ITEM_TABLE IS 23:39:39 27 c NUMBER := 1; -- Counter for table index. 23:39:39 28 item ITEM_OBJECT; 23:39:39 29 items_table ITEM_TABLE := item_table(); 23:39:39 30 CURSOR c1 IS 23:39:39 31 SELECT ename, job FROM emp; 23:39:39 32 BEGIN 23:39:39 33 FOR i IN c1 LOOP 23:39:39 34 item := item_object(i.ename, i.job); 23:39:39 35 items_table.EXTEND; 23:39:39 36 items_table(c) := item; -- Must use something other than loop index. 23:39:39 37 c := c + 1; 23:39:39 38 END LOOP; 23:39:39 39 RETURN items_table; 23:39:39 40 END get_items_table; 23:39:39 41 END; 23:39:39 42 / Type body created. Elapsed: 00:00:00.15 23:39:40 SCOTT@orcl> DECLARE 23:41:03 2 items ITEMS_OBJECT; 23:41:03 3 BEGIN 23:41:03 4 items := items_object(items_object.get_items_table); 23:41:03 5 dbms_output.put_line(items.get_size); 23:41:03 6 END; 23:41:13 7 / 14 PL/SQL procedure successfully completed. Elapsed: 00:00:00.00
items_object构造函数使用一个静态函数get_items_table作为它的实际参数.
静态函数get_items_table返回了集合类型变量items_table.
其中每个元素都是item_object类型的.
--打印集合类型变量items_table中的内容 --使用了item_object对象类型的to_string方法 23:46:10 SCOTT@orcl> DECLARE 23:46:26 2 items ITEM_TABLE; 23:46:26 3 BEGIN 23:46:26 4 items := items_object.get_items_table; 23:46:26 5 FOR i IN 1 .. items.COUNT LOOP 23:46:26 6 dbms_output.put_line(items(i).to_string); 23:46:26 7 END LOOP; 23:46:26 8 END; 23:46:27 9 / [SMITH][CLERK] [ALLEN][SALESMAN] [WARD][SALESMAN] [JONES][MANAGER] [MARTIN][SALESMAN] [BLAKE][MANAGER] [CLARK][MANAGER] [SCOTT][ANALYST] [KING][PRESIDENT] [TURNER][SALESMAN] [ADAMS][CLERK] [JAMES][CLERK] [FORD][ANALYST] [MILLER][CLERK] PL/SQL procedure successfully completed. Elapsed: 00:00:00.01
相关推荐
Considered the best Oracle PL/SQL programming guide by the Oracle community, this definitive guide is precisely what you need to make the most of Oracle’s powerful procedural language. The sixth ...
Use new Oracle Database 11g tools and techniques such as PL/Scope, the PL/SQL hierarchical profiler, and the SecureFiles technology for large objects Build modular PL/SQL applications using ...
Oracle 10g PL/SQL Programming examples
Oracle PL/SQL Programming
Thoroughly updated for Oracle Database 11g Release 2, this edition reveals new PL/SQL features and provides extensive code samples, ranging from simple examples to complex and complete applications, ...
本书内容丰富,结构合理,全面涵盖Oracle Database 11g 的新增特性和实用工具,并提供详细的说明、可剪切-粘贴的语法示例和真实的案例分析。通过学习书中的代码和图例,您不仅能访问和修改数据库信息,编写功能强大...
Oracle database 10g PL/SQL Programming一书的代码
oracle database 11g pl/sql programming,内容是全英文的,我加了一个中文的索引,里面介绍pl/sql编程,很全面,值得学习
At the heart of much of Oracle’s software is PL/SQL—a programming language that provides procedural extensions to Oracle’s version of SQL (Structured Query Language) and serves as the programming ...
oracle8 pl/sql programming 中文 pdf
Use new Oracle Database 11g tools and techniques such as PL/Scope, the PL/SQL hierarchical profiler, and the SecureFiles technology for large objects Build modular PL/SQL applications using ...
Oracle9i PL/SQL Programming 一书中pl sql的代码 浅显易懂 覆盖全面
PL/SQL, Oracle's procedural extension of SQL, is an advanced fourth-generation programming language (4GL). It offers modern features such as data encapsulation, overloading, collection types, ...
Oracle PL/SQL Programming 6th Edition by Steven Feuerstein, Bill Pribyl
Filled with detailed examples and expert strategies from an Oracle ACE, Oracle Database 12c PL/SQL Programming explains how to retrieve and process data, write PL/SQL statements, execute effective ...
This book explains the best way to construct packages, a powerful part of Oracle's PL/SQL procedural language that can dramatically improve your programming productivity and code quality, while ...
application logic move into the Oracle Server, so that PL/SQL programming has become a significant part of the total development process. PL/SQL Developer focuses on ease of use, code quality and...
Oracle PL/SQL Programming( Oracle PL/SQL程序设计 )第5版书中源代码