Question

Forms 6i stored procedure/data block wizard

Asked by: joelund



Oracle Forms builder 6i: Unable to see stored procedures in data block wizard and therefore use data block wizard.
Facts:

Data block wizard can be successfully used to build blocks for tables in this schema (Man)
Can see procedure as a node under Database objects for appropriate schema (Man)
Can successfully execute procedure (proc_emps) in Oracle SQL Plus.

while in data bloxck wizard I click stored procedure radio block and go to next page, enter the procedure (proc_emps) and click refresh. No available cols populate.
 

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2004-06-09 at 09:03:17ID21019264
Tags

forms

,

oracle

,

block

,

procedure

,

6i

Topic

Oracle Product Info

Participating Experts
2
Points
250
Comments
6

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Procedure builder
    Simple question. Where do I get Procedure builder from, is there somewhere I can download it from. I thought it came part of the oracle 8i disk. I have installed everything, but can't find Procedure builder. Please help
  2. Multiple schemas .vs. single schema
    We are developing a multi-user app, that we intend to use Oracle as the DB. We're unsure at this stage whether to have all the data stored in one schema or whether each client should have a separate schema. As the client-base increases there will probably be the need to hav...
  3. DataGrid and Oracle stored procedure
    hi experts, I am trying to use Oracle Stored procedure to do some common operations on oracle table such as EMP table, from a DataGrid on VB.NET form, how to perform select, insert, delete, update records by using oracle stored procedure ? Now I can display EMP on datagrid b...
  4. Oracle Store Procs with Resultset
    Hello, I am getting some difficulty in Calling Oracle Stored Procedure thru PB. I have create one store proc in Oracle that returns multiple records based on the condition given. Ex: my SQL select statement in the store proc is: SELECT empno,ename,job,sal FROM emp WHERE d...
  5. db2 schema
    Dear experts A “schema” in DB2 refers to a qualifying name used to group objects together within a database. from the above statement what exactly is schema in laymans terms. what objects is the author talking about in the above sentence. also does the definition for sche...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: HenkaPosted on 2004-06-09 at 23:16:35ID: 11276545

What does your procedure returns ? I think that it has to be a REF CURSOR or a Table of records.

 

by: schwertnerPosted on 2004-06-10 at 05:45:47ID: 11278732

You have first to create the procedures which will be the base of your new block (instead of table or view).



Using Stored Procedures
You base a data block on a stored procedure when you want to:
• Increase control and security
Using a stored procedure, you do not have to grant select access on the
table to the users, just EXECUTE privileges on the procedure.
• Specify a SELECT statement at run-time
Using a Ref cursor, if the logged-on user is a manager, open the cursor as
SELECT lastname, salary FROM s_emp; otherwise open the cursor as
SELECT lastname, null FROM s_emp.
• Base a block on multiple tables
Using a Ref cursor and depending on some parameter to the procedure,
the cursor could be opened either as SELECT * FROM open_orders
(current data) or SELECT * FROM closed_orders (old data).
• Perform complex computations and decisions
Using a table of records, return the salary of all employees that you
manage, but NULL for the salary of other employees.
• Perform validation and DML on the server side
If your data block has multiple validation lookup or derived fields that
are database-intensive, this method of partitioning the application logic
onto the server can vastly improve the performance of applications.
• Encapsulate logic within a subprogram
• Reduce traffic through array processing using a Ref cursor





Data Block Properties for DML
Property Description
DML Data Target Type Specifies the DML Data Source Type for the data
block
DML Data Target Name Specifies the name of the DML Data Source for the
data block (Only used if DML Data Target Type is
Table.)
(Insert, Update, Delete, Lock)
Procedure Name
Specifies the name of the procedure to be used (Only
used if DML Data Target Type is Procedure.)
(Insert, Update, Delete, Lock)
Procedure Result Set Columns
Specifies the names and datatypes of the
result set columns associated with the
procedure (Only used if DML Data Target
Type is Procedure.)
(Insert, Update, Delete, Lock)
Procedure Arguments
Specifies the names, datatypes, and values
of the arguments that are to be passed to the
procedure (Only used if DML Data Target
Type is Procedure.)

 

by: joelundPosted on 2004-06-10 at 07:03:25ID: 11279460


appreciate the quick responses and the information provided, however, my problem (unable to see stored procedure when using data block wizard in Form Builder (6i) still exists.
As indicated, I can see the stored program unit (proc_name) in the Forms Object Navigator. The proc_name code is listed below and returns a table.

The Data Block wizard works fine for tables and views.


create or replace Procedure proc_name Is
 Type t_namestable Is Table of varchar2(24)
 Index by Binary_integer;
 v_names   t_namestable;
 Begin
 v_names(1) := 'Jon Lund';
 dbms_output.Put_line(v_names(1))
 ;
 End
 ;

 

by: schwertnerPosted on 2004-06-10 at 07:12:44ID: 11279559

There is a basic misunderstanding WHY you have to see a stored procedure when you create a block.
You have to see it, because you want to base the block on this (these) procedures, instead of an Oracle table.
So basically the procedure has at least to query a table in the database. The example you gave indicates that there is not SELECT statement.

 

by: schwertnerPosted on 2004-06-10 at 07:13:09ID: 11279564

Why base a block on a stored procedure?
---------------------------------------
 
Basing a block on a stored procedure is an advanced operation to do the  
following:
 
1. Reduce network traffic through array processing as the sql statements are  
   processed by the pl/sql engine on the server side.
2. Perform complex computations  
3. Update and query multiple tables
4. Perform validation and DML on server-side.
 
 
What is a REF Cursor?
--------------------
 
REF cursors hold cursors in the same way that VARCHAR2 variables hold strings.  
This is an added feature that comes with PL/SQL v2.2.  A REF cursor allows a  
cursor to be opened on the server and passed to the client as a unit rather  
than one row at a time.  One can use a Ref cursor as a target of assignments  
and can be passed as parameters to the Program Units.  Ref cursors are opened  
with an OPEN FOR statement and in all other ways, they are the same as regular  
cursors.
 
 
What is a table of records?
--------------------------
 
A table of records is a new feature added in PL/SQL v2.3.  It is the equivalent  
of a database table in memory.  If you structure the PL/SQL table of records  
with a primary key (an index) you can have array-like access to the rows.  
Table of records differ from arrays in that they are not bound by a fixed lower  
or higher limit.  Nor do they require consecutive index numbers as arrays do.  
Consult a PL/SQL reference manual (version 2.3 or higher) for further  
explanation.  There are three steps involved in creating a table of records.  
The are:
 
1. Declare a record type that the table is going to contain.
2. Declare a new type for the table of record.
3. Finally, declare a  variable using the new type.
 
 
Why base a block on a PL/SQL Table versus a Ref Cursor?
------------------------------------------------------
 
A table of records fetches all the rows from the table.
A reference cursor fetches only those rows that matches your query criteria.
If you are planning to filter the rows with a where clause or your query
returns only few records out of many, you can choose the ref cursor rather than
table of records.  Note that the block properties for number of records set and
buffered affect blocks based on stored procedures.
 
 
CODE EXAMPLES
==============
 
This note explains how to use Table of Records or Ref Cursors as the data query
source and for DML operations using transactional triggers like On-insert,  
On-update and On-lock triggers.  This note provides two examples of basing a  
block on a stored procedure.  The first example will provide sample code for  
single block operations.  The second example will follow with code for  
performing multi-block operations with a master-detail relationship.  
 
 
EXAMPLE A.  Single Block Operations.
 
Use a table with a Primay key. Avoid using Rowid with any select statement.
(Reason explained later).  Follow through and complete each of the 5 steps
below.
 
 
Step1: Create a table named Bonus
---------------------------------
 
CREATE TABLE BONUS(
  EMPNO  NUMBER PRIMARY KEY,
  ENAME  VARCHAR2(50),
  JOB    VARCHAR2(20),
  SAL    NUMBER,
  COMM   NUMBER);
 
 
Step2:  Create a package spec at the database level
---------------------------------------------------
 
PACKAGE bonus_pkg IS
  TYPE bonus_rec IS RECORD(
    empno      bonus.empno%TYPE,
    ename      bonus.ename%TYPE,
    job            bonus.job%TYPE,
    sal            bonus.sal%TYPE,
    comm      bonus.comm%TYPE);
 
  TYPE b_cursor IS REF CURSOR RETURN bonus_rec;
 
-- Statement below needed if block is based on Table of Records
  TYPE bontab IS TABLE OF bonus_rec INDEX BY BINARY_INTEGER;
 
-- Statement below needed if using Ref Cursor
  PROCEDURE bonus_refcur(bonus_data IN OUT b_cursor);
 
-- Statement below needed if using Table of Records
  PROCEDURE bonus_query(bonus_data IN OUT bontab);  
 
--Statements below needed for both Ref Cursor and Table of Records
  PROCEDURE bonus_insert(r IN bonus_rec);
  PROCEDURE bonus_lock(s IN bonus.empno%TYPE);
  PROCEDURE bonus_update(t IN bonus_rec);
  PROCEDURE bonus_delete(t IN bonus_rec);
   
-- If this last function is not included you cannot use the
-- Query -> count hits from the default menu of the forms and  
-- will get error frm-41003  Function cannot be performed here.
  FUNCTION count_query_ RETURN number;
 
END bonus_pkg;
 
 
Step 3.  Create the package body
--------------------------------
 
PACKAGE BODY bonus_pkg IS
 
  PROCEDURE bonus_query(bonus_data IN OUT bontab) IS
    ii NUMBER;
    CURSOR bonselect IS
      SELECT empno, ename, job, sal, comm FROM bonus;
  BEGIN
    OPEN bonselect;
    ii := 1;
    LOOP
      FETCH bonselect INTO
        bonus_data( ii ).empno,
        bonus_data( ii ).ename,
        bonus_data( ii ).job,
        bonus_data( ii ).sal,
        bonus_data( ii ).comm;
      EXIT WHEN bonselect%NOTFOUND;
      ii := ii + 1;
    END LOOP;
  END bonus_query;
 
  PROCEDURE bonus_refcur(bonus_data IN OUT b_cursor) IS
  BEGIN
    OPEN bonus_data FOR SELECT empno, ename, job, sal, comm FROM bonus;
  END bonus_refcur;
 
  PROCEDURE bonus_insert(r IN bonus_rec) IS
  BEGIN
    INSERT INTO bonus VALUES(r.empno, r.ename, r.job, r.sal, r.comm);
  END bonus_insert;
 
  PROCEDURE bonus_lock(s IN bonus.empno%TYPE) IS
    v_rownum NUMBER;
  BEGIN
    SELECT empno INTO v_rownum FROM bonus WHERE empno=s FOR UPDATE OF ename;
  END bonus_lock;
 
  PROCEDURE bonus_update(t IN bonus_rec) IS
  BEGIN
    UPDATE bonus SET ename=t.ename, job=t.job, sal=t.sal, comm=t.comm  
                 WHERE empno=t.empno;
  END bonus_update;
 
  PROCEDURE bonus_delete(t IN bonus_rec) IS
  BEGIN
    DELETE FROM bonus WHERE empno=t.empno;
  END bonus_delete;
 
  FUNCTION count_query_ RETURN NUMBER IS
    r NUMBER;
  BEGIN
    SELECT COUNT(*) INTO r FROM bonus;
    RETURN r;
  END count_query_;
 
END bonus_pkg;
 
 
 
Step 4.  Create the Form Block                            
------------------------------
 
Build a block using the Data Block Wizard with type of data block as "Table or
View" based on the Bonus table.   Now, open the block property sheet to base  
the block on the stored procedures as follows:
 
In the block property sheet,
  *  Set the Query Data Source Type as Procedure.
  *  Set the Query Data Source Name with the appropriate stored procedure.
     In this example, for refcur you will enter "bonus_pkg.bonus_refcur" and
     for table of records you will enter "bonus_pkg.bonus_query".
  Note: One can use either Ref Cursor or Table of Records to perform this  
        query operation.  For this example, either use the procedure  
        bonus_pkg.bonus_query or bonus_pkg.bonus_refcur.
        You do not need to set anything in the "Query Data Source Columns"
        property, as Forms has already done this because you began by creating
        the block with data block as a Table.
 
  *  Set the Query Data Source Arguments with the appropriate argument name for
     that query.  
     In this example, "bonus_data" is the argument name for both refcur and  
     table of records.
 
  *  Set the Type to "Table" for table of records or "Refcursor" for referenced  
     cursor.  
           
  *  Set a Name.
     In this example, we can use "bonus_pkg.bontab" for table of records
     (packagename.table_name) or you can use either "bonus_pkg.b_cursor"  
     or "bonus_data.b_cursor" for a ref cursor.
 
  *  Set Mode to "IN/OUT" as the data is flowing between the client and server
     and viceversa.
 
  *  Set Value (optional)
 
If you skip to set typename, you will hit an error. The possible compilation  
error will be PL/SQL error 103 in the QUERY-PROCEDURE TRIGGER.
 
When you use the "table of records" as the source of query, Forms automatically
creates a trigger like Query-Procedure to populate the values that are sent
from the database through the stored procedure.  
 
  *  Set the DML target type as "Transactional triggers" under the Advanced  
     Database section.  This step is important.  You must specify
     "transactional triggers" to avoid getting an error:
       FRM-40743: THIS OPERATION WITH NO BASE TABLE REQUIRES THE %S TRIGGER.
     at runtime.
     Leave all other properties under the Advanced Database section blank.
     Note: You must use transactional triggers to perform all DML processing  
           as your block is based on stored procedures and not a table or view.
           If you do not provide these triggers (see code in Step 5) you will  
           receive runtime error:  Frm-40401 No Changes To Save when after  
           performing DML operations like insert, delete or update.
 
One more general example of setting the Query Data Source Arguments in the
block property palette could be,  
 
ARGUMENTNAME      TYPE            TYPENAME          MODE       VALUE
-------------     ----            --------          ----       -----
bonus_data     REFCURSOR      bonus_pkg.b_cursor    IN OUT    (leave blank)
                              Or bonus_data.b_cursor
                         OR
bonus_data     TABLE          bonus_pkg.bontab      IN OUT    (leave blank)
 
 
Step 5.  Create Transactional Triggers
--------------------------------------
Transactional triggers must be created a the block level as follows:
 
* On-insert trigger  
 
  DECLARE
    r bonus_pkg.bonus_rec;
  BEGIN
    r.empno := :bonus.empno;
    r.ename :=:bonus.ename;
    r.job := :bonus.job;
    r.sal := :bonus.sal;
    r.comm := :bonus.comm;
 
    bonus_pkg.bonus_insert(r);
  END;
 
 
* On_lock trigger
 
  bonus_pkg.bonus_lock(:bonus.empno);
 
 
* On-update trigger
 
  DECLARE  
    t bonus_pkg.bonus_rec;
  BEGIN
    t.empno :=:bonus.empno;
    t.ename :=:bonus.ename;
    t.job := :bonus.job;
    t.sal := :bonus.sal;
    t.comm := :bonus.comm;
 
    bonus_pkg.bonus_update(t);
  END;
 
 
* On-delete trigger
 
  DECLARE
    t bonus_pkg.bonus_rec;
  BEGIN
    t.empno :=:bonus.empno;
    t.ename :=:bonus.ename;
    t.job := :bonus.job;
    t.sal := :bonus.sal;
    t.comm := :bonus.comm;
 
    bonus_pkg.bonus_delete(t);
  END;
 
 
* On-count trigger  (optional)
  Note.  Because you have based your block on a stored procedure, Form's
         default processing will not return the number of query hits.  This  
         trigger takes the place of the default processing and will return  
         the number of query hits.
 
  DECLARE
    recs NUMBER;
  BEGIN
    recs := bonus_pkg.count_query_;
    SET_BLOCK_PROPERTY('bonus', query_hits,recs);
  END;
 
 
You now have completed the process for basing a block on a stored procedure for
single block operations.
 
 
=============================================================================
 
EXAMPLE B.  Multi-block opererations with master-detail relationship
 
Basing a block on a stored procedure (Multi block operation, having master
detail relationship).
 
Suppose you are passing a value from master block to the detail block to
perform query operation, perform the following steps:
 
 
Step1:  verification
--------------------
  BEFORE ATTEMPTING TO DO THIS, VERIFY THE PRESENCE OF INTEGRITY CONSTRAINTS
  FOR THE TABLES INVOLVED IN THIS OPERATION.
  Verify if the tables have Primary key and Foreign Key relationship.
  Your Physical Database design is very important. Otherwise, you will be
  getting errors like  
    ORA-6502  Pl/sql: Numeric value error or  
    ORA-4098  Trigger 'X' is invalid and failed revalidation.  
    ORA-4068  If any column name is not properly defined in the select
              statement of the stored procedure.
   
 
 
Step2:  Create a package spec at the database level
---------------------------------------------------
 
PACKAGE emp_pkg IS
  TYPE emprec is RECORD(
    empno    emp.empno%type,
    ename    emp.ename%type,
    job      emp.job%type,
    mgr      emp.mgr%type,
    hiredate emp.hiredate%type,
    sal      emp.sal%type,
    comm     emp.comm%type,
    deptno   emp.deptno%type);
  TYPE empcur IS REF CURSOR RETURN emprec;
  TYPE emptab IS TABLE OF emprec INDEX BY BINARY_INTEGER;
 
-- This procedure uses refcursor for query operation, it sends the data
-- from the stored procedure to the client.
  PROCEDURE empquery_refcur(emp_data IN OUT empcur,
                            v_dno    IN     NUMBER);
 
-- This procedure uses table of records for query operation.
-- One can use either ref cursor or table of records for query operation.
  PROCEDURE empquery(emp_data IN OUT emptab,
                     v_dno    IN     NUMBER);
 
-- This procedures inserts the data passed as a record from the emp block
-- to the emp table.
  PROCEDURE emp_insert(r IN emprec);
 
-- Empno is getting passed from emp block to the stored procedure, this
-- procedure is to lock that specific row that has that empno.
  PROCEDURE emp_lock(s IN emp.empno%TYPE);
 
  PROCEDURE emp_update(t IN emprec);
 
  PROCEDURE emp_delete(t IN emprec);
 
-- If this last function is not included you cannot use the
-- Query -> count hits from the default menu of the forms and  
-- will get error frm-41003  Function cannot be performed here.
  FUNCTION count_query_ RETURN NUMBER;  
 
END emp_pkg;
 
 
Step 3.  Create the package body
--------------------------------
 
PACKAGE BODY emp_pkg IS
 
  PROCEDURE empquery(emp_data IN OUT emptab,
                     v_dno    IN     NUMBER) IS
    ii NUMBER;
    CURSOR empselect IS  
      SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno
        FROM emp  
       WHERE deptno = nvl(v_dno, deptno);
  BEGIN
    OPEN empselect;
    ii := 1;
    LOOP
      FETCH empselect INTO
        emp_data(ii).empno,
        emp_data(ii).ename,
        emp_data(ii).job,
        emp_data(ii).mgr,
        emp_data(ii).hiredate,
        emp_data(ii).sal,
        emp_data(ii).comm,
        emp_data(ii).deptno;
        EXIT WHEN empselect%NOTFOUND;
          ii := ii + 1;
     END LOOP;
   END empquery;
 
   
  PROCEDURE empquery_refcur(emp_data IN OUT empcur,
                            v_dno    IN     NUMBER) AS
  BEGIN
    OPEN emp_data FOR
      SELECT empno, ename, job, mgr, hiredate, sal, comm, deptno
        FROM emp
       WHERE deptno = nvl(v_dno, deptno);
  END empquery_refcur;                                                          
                                                                                 
                                                                                 
                                                                                 
                                                                                 
                                                                                 
                                                                                 
                                                                                 
                                                                                 
                                                                                 
                                                                                 
                                                                                                                  !
                                     
  PROCEDURE emp_insert(r IN emprec) IS
  BEGIN
    INSERT INTO emp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
    VALUES (r.empno, r.ename, r.job, r.mgr, r.hiredate, r.sal,
            r.comm, r.deptno);
    COMMIT;
  END emp_insert;
 
  PROCEDURE emp_lock(s IN emp.empno%TYPE) IS
    v_rownum NUMBER;
  BEGIN
    SELECT empno
      INTO v_rownum
      FROM emp
     WHERE empno = s
       FOR UPDATE OF ename;
  END emp_lock;
 
  PROCEDURE emp_update(t IN emprec) IS
  BEGIN
    UPDATE emp
       SET ename = t.ename,
           job = t.job,
           mgr = t.mgr,
           hiredate = t.hiredate,
           sal = t.sal,
           comm = t.comm,
           deptno = t.deptno
     WHERE empno = t.empno;
  END emp_update;
 
  PROCEDURE emp_delete(t IN emprec) IS
  BEGIN
    DELETE
      FROM emp
     WHERE empno = t.empno;
  END emp_delete;
 
  FUNCTION count_query_ RETURN NUMBER IS
    r NUMBER;
  BEGIN
    SELECT count(*)
      INTO r
      FROM emp;
    RETURN r;
  END count_query_;
 
END emp_pkg;
 
 
Step 4.  Create the Form Block                            
------------------------------
 
Build the block with datablock type as "table or view" for both the master
(dept) and detail block (emp). Later the block property sheet will be adjusted
for the detail block to be based on stored procedure.
The blocks can be built manually also, but, using wizard is preferrable. Here,
you have the choice of having tab canvas.
 
Create the relationship between these blocks either explicitly or at the time
of creating the block using wizard, refer the later part of this note for more
information on this.
 
In the detail block propertysheet, (emp block)
  * set the Query Data Source Type as Procedure.
  * set the Query Data Source Name with the appropriate name of the stored
    procedure.
    In this case, One can use either the Ref Cursor or Table of Records to
    perform this query operation. So, in this example, either use the procedure
      emp_pkg.empquery
    or  
      emp_pkg.empquery_refcur
 
Because you began creating the block with data block as Table or view, you do
not need to set anything in the Query Data Source Columns as the Forms does
that job.
 
  * set the Query Data Source Arguments with the appropriate argument name for
    that query.
    In this case, emp_data is the argument name for both ref cursor and table
    of records
  * set the Type to table or refcursor, depending on the procedure you have
    chosen. This example uses the "Table".
  * set the Type Name to the appropriate type, this will be emp_pkg.emptab
    If you choose the ref cursor, it would have been emp_pkg.empcur or
    emp_data.refcur
  * set Mode to "IN/OUT" as the data is flowing between the client and server
    and viceversa.
  * set Value (optional)
 
  * repeat above steps for the other argument of the procedure, deptno.
    The appropriate values can be found in the table below
 
Yet another general example could be,
 
ARGUMENTNAME   TYPE            TYPENAME            MODE       VALUE
------------   ----            --------            ----       -----
emp_data       REFCURSOR       emp_pkg.empcur      IN OUT     (leave it blank)
                            OR
emp_data       TABLE           emp_pkg.emptab      IN OUT  
                           
                            AND
 
v_dno          NUMBER          dept.deptno%type    IN         :dept.deptno
 
If you skip to set typename, you will hit an error. The possible compilation  
error will be:
  PL/SQL error 103 in the QUERY-PROCEDURE TRIGGER.
 
When you use the "table of records" as the source of query, Forms automatically
creates a trigger like Query-Procedure to populate the values that are sent
from the database through the stored procedure.  
 
  * Set the DML target type as "Transactional triggers" under the Advanced  
    Database section. You must specify "transactional triggers" to avoid
    getting error:
      FRM-40743: THIS OPERATION WITH NO BASE TABLE REQUIRES THE %S TRIGGER.
    at runtime. Leave all other properties under the Advanced Database section
    blank.
    Note: You must use transactional triggers to perform all DML processing as
          your block is based on stored procedures and not a table or view.
          If you do not provide these triggers (see code in Step 5) you will  
          receive runtime error:
            Frm-40401 No Changes To Save
          after performing DML operations like insert, delete or update.
 
 
Step 5.  Create Transactional Triggers
--------------------------------------
Then, from the forms at detail block level (emp), you have to create the
following triggers:
 
* On-insert trigger
 
  DECLARE
    r emp_pkg.emprec;
  BEGIN
    r.empno := :emp.empno;
    r.ename :=:emp.ename;
    r.job := :emp.job;
    r.mgr := :emp.mgr;
    r.hiredate := :emp.hiredate;
    r.sal := :emp.sal;
    r.comm := :emp.comm;
    r.deptno := :emp.deptno;
     
    emp_pkg.emp_insert(r);
  END;
 
 
* On_lock trigger
 
  emp_pkg.emp_lock(:emp.empno);
 
 
* On-update trigger
 
  DECLARE
    t emp_pkg.emprec;
  BEGIN
    t.empno := :emp.empno;
    t.ename := :emp.ename;
    t.job := :emp.job;
    t.mgr := :emp.mgr;
    t.hiredate := :emp.hiredate;
    t.sal := :emp.sal;
    t.comm := :emp.comm;
    t.deptno := :emp.deptno;
 
    emp_pkg.emp_update(t);
  END;
 
 
* On-delete trigger
 
  DECLARE
    t emp_pkg.emprec;
  BEGIN
    t.empno := :emp.empno;
    t.ename := :emp.ename;
    t.job := :emp.job;
    t.mgr := :emp.mgr;
    t.hiredate := :emp.hiredate;
    t.sal := :emp.sal;
    t.comm := :emp.comm;
    t.deptno := :emp.deptno;
 
    emp_pkg.emp_delete(t);
  END;
 
 
* On-count trigger
 
  DECLARE
    recs NUMBER;
  BEGIN
    recs := emp_pkg.count_query_;
    set_block_property('emp', query_hits, recs);
  END;
 
-- This On-Count trigger is needed. The forms default
-- processing will not return the query hits as you have  
-- based the block on a stored procedure.
 
 
Step 6.  Change the delete record behavoiur
-------------------------------------------
 
Make sure the "delete record behaviour" property of the relation is set to
isolated (non-isolated is the default in Developer 6).
 
 
You now have completed the process for basing a block on a stored procedure for
Master-Detail operations.
 
 
===============================================================================
Questions:
 
1. What will happen if you change the "delete record behaviour" from isolated
   to non-isolated or cascading?
 
   If you change the "Delete record behaviour" from isolated to non-isolated,
   the On-Check-Delete-Master trigger will be created by forms in the master
   block. This will not understand the stored procedure you have used as a
   query data source for the detail block. As a result, you will get a
   Compilation error in the On-Check-Delete-Master trigger that will be like:
     Pls-201 procedure name must be declared.
 
   Similarly, if you change the "Delete record behaviour" from isolated to
   cascading, the forms generates the Pre-Delete trigger in the master block
   which will give a compilation error as well, as the master block will not
   understand the procedure for the query data source on which the detail block
   is based on.  
   It will be costly to have integrity constraint at form level also as the
   pre-delete trigger repeats the same job as the constraints declared at
   database side.
   So, do not try to change the "Delete Record Behaviour".
   See also bug:761722
 
   If you have the proper integrity constraints added to your tables, it will
   be automatically taken care of at the time of committing the record.
   For example, when you delete a master record while child records are there,
   at the time of saving this change, the form will provide an error message:
     Frm-40510: Oracle error: Unable to delete record.
 
   If you do not have a foreign key constriant at all, and attempt to set the
   "delete behaviour" to cascading, it will give you:
     Frm-30409 Delete record behaviour is invalid.
 
 
2. Why use Primary key and not rowid ?
 
   The On_Lock trigger replaces the default forms locking, as a side effect
   prevents Forms from obtaining the ROWID for the row. In consequence you must
   define a Primary Key for the block and use this PK to be passed as a
   parameter to the stored procedure.
   And also, your block must have a PK, otherwise, you will hit:
     Frm-30100 Block must have atleast one Primary Key item.
 
 
3. How to set the query criteria for detail block passing a value from the
   master block?
 
   If you have chosen the tab canvas as the canvas type and if you want to set
   the query criteria in the detail block the same as master block, you can
   create a Key-Exeqry trigger at block level for the master block and call
   execute_query from there;
   Also, you can create a When-Tab-Page-Changed trigger at form level to pass
   the query criteria from the master block to the detail and type the
   following:
 
     DECLARE
       page_name varchar2(10);
       tab_id tab_page;
       tab_id2 tab_page;
     BEGIN
       page_name := get_canvas_property('CANVAS8', TOPMOST_TAB_PAGE);
       IF page_name = 'PAGE11' THEN
         go_item('dept.deptno');
       ELSE
         go_item('empno');
         execute_query;
       END IF;
     END;
 
   You can set the "Copy value from item" of the item's property sheet in the
   detail block of the item that has relationship with the master.
   Here, in this example you can set the "copy value from item" property of the
   deptno in the emp block to "dept.deptno".
 
   See the note:1078147.6 for more explanation.
 
 
4. What to remember if you build the block manually?
 
   In case of Master-Detail blocks, if you are passing a column to the stored
   procedure that inturn returns data to the detail block and if the detail
   block also has the same column present, you have to set the Column Name
   Property of that specific text item to null or blank. Otherwise, you will be
   getting:
     Frm-40350 Query Caused no records to be retrieved.
   
   In this case, if you build the block manually for the detail block, the
   Column Name Property of the deptno in the dept block must be blank as it is
   taken care of by the stored procedure that uses a table of records or a ref
   cursor.
 
 
5. Getting the error "Wrong no. of arguments to populate_block in
   query_procedure". What should I do?
 
   If you attempt to change the block properties manually to use refcursor from
   table of records, the Query data source name property and Query data source
   arguments should be set properly. If you feel you set it right and are still
   getting this compilation error, drop that procedure and let the forms
   builder generate a new one for you.
 
 
6. My query is performing extremely slow?
 
   If your query matches or retrieves only small amount of records or if you
   are using where clause to filter the query results, then use a refcursor
   rather than using a table of records. As a ref cursor returns only the
   records that match the query condition. But, a table of records tries to
   fetch all the records. So, performance will be slower with table of records.
 
 
Tips
----
 
  Provide an exceptional handler for all the possible ora errors like
  ORA-4098 and ORA-4068.
  If you get:
    ORA-6502 Pl/sql: Numeric or Value error
  your table definition of column lengths do not go with the datatype or length
  of the text items in the forms.
  Use the debugger to see what values are getting passed from client to server
  and viceversa.

 

by: joelundPosted on 2004-06-10 at 07:41:50ID: 11279862

Thanks schwertner problem solved

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...