1、基于过程的块
在包头中说明的过程,在包体中一定要定义,定义必须连参数的名称也必须一至。
在使用过程(procedure)建立数据块的时候,在包中分别建立查询、插入、更新、删除、锁定5个过程。用来操作数据。其中,查询的IN OUT的参数为REF CURSOR类型,而对表单记录的DML和加锁语句,IN OUT的参数为TABLE类型。
例子:
下面就是一个包中对记录进行查询和插入。
包头:
create or replace package test_emp_maint is
-- Public type declarations
TYPE emp_t IS RECORD(
id test02.id%TYPE,
name test02.name%TYPE,
sex test02.sex%TYPE,
age test02.age%TYPE,
manager_id test02.manager_id%TYPE);
--游标类型,用于查询参数
TYPE rc_emp IS REF CURSOR
RETURN emp_t;
--表类型,用于DML以及加锁
TYPE t_emp IS TABLE OF
emp_t
INDEX BY BINARY_INTEGER;
PROCEDURE slct(
p_empqry IN OUT rc_emp);
PROCEDURE ins(
p_emprec IN OUT t_emp);
end test_emp_maint;
包体:
create or replace package body test_emp_maint is
-- SELECT DATA
PROCEDURE slct(
p_empqry IN OUT rc_emp)
IS
BEGIN
OPEN p_empqry
FOR
SELECT * from test02;
END;
-- INSERT DATA
PROCEDURE ins(
p_emprec IN OUT t_emp)
IS
--v_message VARCHAR(100);
BEGIN
--v_message := 'INSERT INTO TABLES TEST02 RECORDS';
For v_ct IN 1 .. p_emprec.count
LOOP
INSERT INTO test02(
id,
name,
sex,
age,
manager_id)
VALUES (
p_emprec( v_ct ).id,
p_emprec( v_ct ).name,
p_emprec( v_ct ).sex,
p_emprec( v_ct ).age,
p_emprec( v_ct ).manager_id
);
END LOOP;
END;
END test_emp_maint;
2、当在数据块中设定插入、更新的相关属性之后,FORM BUILDER会自动创建INSERT-PROCEDURE/UPDATE-PROCEDURE/DELETE-PROCEDURE等过程。
NOTES:在填入参数类型的时候,一定要将参数类型写完整,将包的名字写上。例如上述插入参数的类型应该为test_emp_maint.t_emp,而不是t_emp。
3、数据库服务器和表单:
在何处放置代码:数据库服务器还是表单
面向表单的代码放置在表单一侧,因为服务器不能解释类似于SET_BLOCK_PROPERTY这样的代码。数据库对象的代码则在表单和服务器上都可以存放。
4、其它数据库代码源:
1、数据库触发器
2、基于视图的块
3、基于过程的块
5、程序库的三种级别:
通用程序库(可分为对数据库操作和不对数据库操作)、应用程序专用的程序库(应用程序调用的数据程序包的代码)、表单专用程序库
6、放置代码的通用准则:
尽可能多的使用存储在数据库服务器中的代码实现对数据的访问和操作。Forms不应该使用PL/SQL代码打开游标或者执行缺省查询,以及DML机制外的查询。
写的代码尽量通用。如果创建表单用的专用的实用程序是可重用的,则将其放置于程序库中。
使用Package来使代码模块化。
如有可能在Form的最高级编写触发器代码。(有三个等级Form->Block->Item)
7、全局变量在session的生命周期内存在。
赋值:GLOBAL.my_var := TO_CHAR(:order.total * .85);
使用:calculate_discount(TO_NUMBER(:GLOBAL.my_var));
Destory:Erase('GLOBAL.my_var');
8、调用内置程序:
Go_Item('customer.cust_id');
Focus到customer块的cust_id项。
9、使用函数:
注意函数的返回类型。
:control.item_A := Message_Text;
Go_Item(Get_Block_Property('customer',LAST_ITEM));
IF Show_LOV('customer_list') THEN
Message('Good Selection.');
ELSE
Message('No Customer was Selected.');
END IF;
10、传递参数给子程序:
Resize_Window (window_name, width, height);
Resize_Window('my_window',50,35);
11、使用常量:
Exit_Form(DO_COMMIT,NO_ROLLBACK);
12、使用默认的参数值:
Open_Form('order_entry');
Open_Form('order_entry',ACTIVATE,NO_SESSION);
13、通过名字引用Form Builder中的对象:
Resize_Window('status_window',50,35);
'block_name.item_name'
'record_group_name.column_name'
'blockname.columnname_itemname'
14、引用Form Builder中项目的值:
:ord.total := price * .85;
15、通过内部ID引用Form Builder中的对象:
DECLARE
id_var WINDOW;
BEGIN
id_var := Find_Window('my_window');
END;
使用内部ID的理由:
提高性能,易于维护
16、系统变量:基于表单级,例如SYSTEM.BLOCK_STATUS
17、调用用户命名的触发器:
只能在内建触发器/菜单命令/用户命名的子程序调用。用户命名的触发器只能在特定位置存在,大多数情况是用户编写子程序,然后在触发器或者菜单命令中调用。
18、触发器有如下类目:
Block processing triggers
Interface event triggers
Master-Detail triggers
Message-handling triggers
Navigational triggers
Query-time triggers
Transactional triggers
Validation triggers
Other triggers
19、使用外部连接可以将表连接在自己身上。
在某些情况下,使得字段信息成为统一记录的一部分,按照这种方式建立视图,可以大大减少网络流量。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10484922/viewspace-976094/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/10484922/viewspace-976094/