(转)在PB中用oracle的存储过程返回记录集做数据源来生成数据窗口 首先oracle的存储过程写法与MSSQL不一样,差别比较大。
如果是返回数据集的存储过程则需要利用oracle的包来定义游标。 但是若按正规的oracle写法,存储过程写在包体里面,
如果这样的话,PB会找不到此存储过程(如果用直连的方式)(如果用ODBC的方式则有可能不能正常识别存储过程的参数) 因此我们需要将存储过程单独写。
首先我们来看下oracle正规的返回结果集的存储过程的写法
方法一:
create or replace package pkg_Sp_Changebill --基于更改单的包
--创建包(因为oracle 的存储过程若想要返回记录集则需要利用游标的方式来实现)
as
Type Cur_myRecord Is ref Cursor RETURN item%RowType;
procedure sp_mx3_wgggcp(stritemid varchar2, cur_List out cur_MyRecord);
end pkg_Sp_Changebill;
/
create or replace package body pkg_Sp_Changebill
as
procedure sp_mx3_wgggcp(stritemid varchar2,cur_List out cur_MyRecord)
as
Begin
--存储过程的执行体
open cur_List for select * from item where itemid =stritemid ;
end sp_mx3_wgggcp;
end pkg_Sp_Changebill;
如果按上述写法,则在PB中如果是按直接方式来连接数据库的则会找不着这个存储过程,如果是按odbc方式来连接数据库的则能找到些存储过程但是无法正确识别参数。
/**************************************************************************************************************/
重要区别:
方法一,是先建包头声明要实现的存储过程,再建包体且在包体中实现声明中的存储过程,但包体中的存储过程不是一个完全意义上的独立的存储过程创建语法(缺少create or replace procedure..);
方法二、例子2、例子3,都是先创建包头及参数的声明(如游标类型、记录类型、基本类型等),但是并没有声明要实现的存储过程、函数,
而是单独再另外创建一个独立的存储过程,而不是在包体中实现存储过程。单独创建的存储过程是一个具有完整创建语法的存储过程,是一个独立的存储过程,但是该存储过程的参数(如果有需要用到)是要参照引用包头中声明的参数类型。如例子中的游标类型输出参数。
/**************************************************************************************************************/
方法二:
下面这种写法是没有将存储过程包含在包里的:
create or replace package pkg_Sp_Changebill3
as
Type Cur_myRecord Is ref Cursor RETURN item%RowType; --指明此游标是按item表记录的形式返回
end pkg_Sp_Changebill3;
/
create or replace procedure sp_mx3_wgggcp3(stritemid varchar2, cur_List out pkg_Sp_Changebill3.cur_MyRecord --游标可直接用 包名.游标名
as
Begin
--存储过程的执行体
open cur_List for select * from item where itemid = stritemid;
end sp_mx3_wgggcp3;
在直连方式下能找到此存储过程且能正常识别参数。在odbc方式下能找到这个存储过程,但是参数不能正确识别。
================================================================
【例子2】
下面的例子创建的包名和存储过程名,在使用时最好在包名和存储过程前面加上用户名,如:用户名.包名.存储过程名,user.pkgNmae.prcName( ....)
Oracle包的应用——使用存储过程作为数据窗口对象的数据源 第一步:创建包
CREATE OR REPLACE PACKAGE SONGZHENYI.visitOfTimeInfor -- 注意:用户名.包名
AS --为了使存储过程返回一个结果集,第一步:声明一个记录;第二步;声明一个引用游标; TYPE recordePatVist IS RECORD ( charPatientId pat_visit.patient_id%TYPE, numPatientVisitId pat_visit.visit_id%TYPE, charToDept pat_visit.dept_admission_to%TYPE, charToDateTime pat_visit.admission_date_time%TYPE );--声明一个引用游标
TYPE cursorPatVist IS REF CURSOR RETURN recordePatVist;);
END visitOfTimeInfor;第二步:创建存储过程
CREATE OR REPLACE PROCEDURE SONGZHENYI.prcResultPatVisit (
numVisitId IN pat_visit.visit_id%TYPE, curResult OUT visitOfTimeInfor.cursorPatVist)ISBEGIN OPEN curResult FOR SELECT patient_id, visit_id, dept_admission_to, admission_date_time FROM pat_visit WHERE visit_id > numVisitId AND dept_discharge_from IS NOT NULL;END prcResultPatVisit;第三步:PB操作部分
数据源选择存储过程即可。其余部分雷同。
【例子3】 下面是国外的几个例子,对基础学习比较好:
-- Name: sp_as_source_for_dw.sql
-- Author: Terry Dykstra [TeamPS]-- Canadian Forest Oil Ltd.-- Date: 1998/05/09-- Requirements: Oracle 7.2 or later-- Notes: You define a package header that uses a ref cursor.(声明包头,使用游标)-- Then you create a stand-alone procedure that references the result set defined in the package header.(创建一个独立的存储过程,而不是在包体创建时实现存储过程)
-- Now create a datawindow using stored procedure as source and select the procedure-- Settings: DBParm PBDBMS=0-- Oracle privileges: any of EXECUTE ANY PROCEDURE, CREATE PROCEDURE, CREATE ANY PROCEDURE, depending -- on what your DBA allows.-- Run this script from sql/plus. -- Create example table-- ==============================================================================drop table work_orders/create table work_orders (company varchar2(3),order_no varchar2(10),order_date date)/insert into work_orders values ('ABC','1000', to_date('1999/03/05','yyyy/mm/dd'))/insert into work_orders values ('ABC','1001', to_date('1999/03/07','yyyy/mm/dd'))/insert into work_orders values ('ABC','1002', to_date('1999/03/06','yyyy/mm/dd'))/insert into work_orders values ('BCD','1002', to_date('1999/03/06','yyyy/mm/dd'))/insert into work_orders values ('BCD','1005', to_date('1999/03/15','yyyy/mm/dd'))/commit/-- 1.Create Package. Name: a_demo (无输入参数)-- ==============================================================================CREATE OR REPLACE PACKAGE a_demo IS TYPE my_result_set IS REF CURSOR RETURN work_orders%ROWTYPE;END a_demo;/-- Create Procedure. Name: proc_demo-- References package a_demo-- ==============================================================================CREATE OR REPLACE PROCEDURE proc_demo (out_result IN OUT a_demo.my_result_set) AS BEGIN-- return result to datawindow OPEN out_result FOR SELECT * FROM work_orders;END proc_demo;/-- ==============================================================================-- 2.Similar example, but now using one retrieval argument-- Create Package. Name: a_demo2(有输入参数)-- ==============================================================================CREATE OR REPLACE PACKAGE a_demo2 IS TYPE my_result_set IS REF CURSOR RETURN work_orders%ROWTYPE;END a_demo2;/-- Create Procedure. Name: proc_demo2-- References package a_demo2-- ==============================================================================CREATE OR REPLACE PROCEDURE proc_demo2 (as_comp IN VARCHAR2, out_result IN OUT a_demo2.my_result_set) AS BEGIN-- return result to datawindow OPEN out_result FOR SELECT * FROM work_orders WHERE company = as_comp;END proc_demo2;/-- Create Procedure. Name: proc_demo2
-- References package a_demo2a-- ==============================================================================CREATE OR REPLACE PROCEDURE proc_demo2a (ad_orderdate IN DATE, out_result IN OUT a_demo2.my_result_set) ASBEGIN-- return result to datawindow OPEN out_result FOR SELECT * FROM work_orders WHERE order_date = ad_orderdate;END proc_demo2a;/-- ==============================================================================
-- 3.Similar example, but now using one retrieval argument and record type-- Create Package. Name: a_demo3(使用记录类型)-- ==============================================================================CREATE OR REPLACE PACKAGE a_demo3 IS TYPE the_record_set IS RECORD ( ls_company varchar2(3), ll_order_count number(3) ); TYPE my_result_set IS REF CURSOR RETURN the_record_set;END a_demo3;/-- Create Procedure. Name: proc_demo3-- References package a_demo3-- ============================================================================== CREATE OR REPLACE PROCEDURE proc_demo3 (as_comp IN VARCHAR2, out_result IN OUT a_demo3.my_result_set) ASBEGIN-- return result to datawindowOPEN out_result FOR SELECT company, count(*) FROM work_orders WHERE company = as_compGROUP BY company;END proc_demo3;//**********************************************************************************************/
下面是在包体中实现包头中声明的存储过程、函数。但是PB会找不到此存储过程及可能不能正常识别存储过程的参数,
因此,必须首先创建一个虚拟的(或说假的)存储过程,且该存储过程与包中声明的存储过程具有相同的参数类型。
/**********************************************************************************************/
/* Use stored procedure within package body. To use this in the DW, specify:
execute theowner.A_DEMO4.PROC_DEMO4;0 AS_COMP = :AS_COMPNote: since the PB DW painter cannot see the procedure within the package, you must first create a dummy stand-alone procedure that has the same arguments. For this example you can use the proc_demo2procedure *//**********************************************************************************/-- Create Package. Name: a_demo4-- ==============================================================================CREATE OR REPLACE PACKAGE a_demo4 IS TYPE my_result_set IS REF CURSOR RETURN work_orders%ROWTYPE; PROCEDURE proc_demo4 (as_comp IN VARCHAR2, out_result IN OUT a_demo4.my_result_set);END a_demo4;/ CREATE OR REPLACE PACKAGE BODY a_demo4 IS PROCEDURE proc_demo4 (as_comp IN VARCHAR2, out_result IN OUT a_demo4.my_result_set) ISBEGIN-- return result to datawindowOPEN out_result FOR SELECT * FROM work_orders WHERE company = as_comp;END proc_demo4;END a_demo4;//***************************************************************************/看完这段例子,对pb利用oracle8i存储过程做数据源问题应该有认识了,我自己对这方面也有很多疑问,以后多多交流.