Wednesday, July 10, 2013

What is ref cursor?

What is ref cursor? What is the purpose of using ref cursor?

A ref cursor is like an ordinary PL/SQL cursor in that it acts as a pointer to the result set of the cursor with which it is associated. However, the difference is that a ref cursor can be assigned to different result sets whereas a cursor is always associated with the same result set.

The real purpose of ref cursors is to be able to share cursors and result sets between the client and the Oracle server or between different subroutines. For example you might open a cursor in an Oracle Forms client and then continue working with the cursor on the server or you might open a cursor in say a Java program and then continue working with it in a PL/SQL stored procedure.


Let's start with a simple function that opens a ref cursor and passes it back

CREATE OR REPLACE FUNCTION xx_reftest
   RETURN sys_refcursor
IS
   cur   sys_refcursor;
BEGIN
   OPEN cur FOR 'SELECT empno,ename FROM emp';

   RETURN cur;

END;

Now, if we look at using this through SQL*Plus we first create ourselves a ref cursor variable to accept the results of the function, and then call the function to get the ref cursor back.
SQL> var rc refcursor;
SQL> exec :rc := xx_reftest ();
PL/SQL procedure successfully completed.

Ok, so our variable ‘rc’ has our ref cursor.
If we use SQL*Plus print command will print the record set data.
SQL> print rc;

     EMPNO ENAME
---------- ----------
      7839 KING
      7698 BLAKE
      7782 CLARK
      7566 JONES
      7788 SCOTT
      7902 FORD
      7369 SMITH
      7499 ALLEN

So our ref cursor returns the rows we wanted from the employee table.

Let's look at that again.

SQL> print rc;
SP2-0625: Error printing variable "rc"

 What's happened here?  Why can't we print the data that's in our ref cursor again?
A common mistake that people believe is a ref cursor actually contains the result data from the query. In truth, the ref cursor doesn't contain any data at all; it's just a pointer to the query.
So why did the first print statement print out the results?
SQL*Plus looked at the ref cursor and saw that it was an open cursor.  As such it went into a loop, fetching each row of data from the database, using the ref cursor as its reference (pointer) to the relevant query, and displaying each row of data until it had no more rows to fetch.  Once it's fetched all the rows it closes the cursor.  That’s the power of ‘print’ command.
Therefore, when we tried to print the ref cursor a second time, we got an error because SQL*Plus looked at the cursor, saw it was not an open cursor and couldn't perform the task of printing anything.



Let's look at some more examples.

DECLARE
   TYPE xx_cur IS REF CURSOR;        --Ref cursor type declaration

   my_cur   xx_cur;                  --Declare ref cursor variable
   xx_emp   emp%ROWTYPE;
BEGIN
   OPEN my_cur FOR SELECT * FROM emp; --Assigning the record set to cursor variable

   FETCH my_cur INTO   xx_emp;

   CLOSE my_cur;

END;


From 9i onwards we can replace the below statements

TYPE xx_cur IS REF CURSOR;
   my_cur   xx_cur;      

By using the below single statement

my_cur   sys_refcursor;            


Example:

DECLARE
  
   my_cur   sys_refcursor;               --Declare ref cursor variable
   xx_emp   emp%ROWTYPE;
BEGIN
   OPEN my_cur FOR SELECT   * FROM emp; --Assigning the record set to cursor variable

   FETCH my_cur INTO   xx_emp;

   CLOSE my_cur;

END;

Example for cursor re-uses

DECLARE
   TYPE xx_cur IS REF CURSOR;

   my_cur    xx_cur;
   xx_emp    emp%ROWTYPE;
   xx_dept   dept%ROWTYPE;
BEGIN
   --cursor pointing to record set of dept table
   OPEN my_cur FOR SELECT * FROM dept;

   FETCH my_cur INTO xx_dept;

   CLOSE my_cur;

   --cursor pointing to record set of emp table
   OPEN my_cur FOR SELECT * FROM emp;

   FETCH my_cur INTO xx_emp;

   CLOSE my_cur;
END;

Example for opening the ref cursor in one Oracle PL/SQL procedure and fetching in another PL/SQL block


CREATE OR REPLACE PROCEDURE xxad_ref_test (cur OUT sys_refcursor)
AS
BEGIN
   DBMS_OUTPUT.put_line ('start of xxad_ref_test procedure');

   OPEN cur FOR SELECT   * FROM emp;
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line ('errors:-' || SQLERRM);
END;

Calling the procedure in PL/SQL block


DECLARE
   cur1     sys_refcursor;
   xx_emp   emp%ROWTYPE;
BEGIN
   DBMS_OUTPUT.put_line ('Calling procedure');

   xxad_ref_test (cur1);

   DBMS_OUTPUT.put_line ('End of procedure calling');

   LOOP
      FETCH cur1 INTO   xx_emp;

      EXIT WHEN cur1%NOTFOUND;
      DBMS_OUTPUT.put_line (xx_emp.ename);
   END LOOP;
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line ('Errors ' || SQLERRM);

END;

Thursday, July 4, 2013

Apps Concurrent Program In Shell Script

Below code will demonstrate how to call the Apps XML publisher concurrent program through shell script.

#!/bin/sh
# ------------------------------------------------------------------
# Initialize variables.
#-------------------------------------------------------------------
OraUsr=$1
export OraUsr
UserId=$2  
export UserId                
UsrName=$3
export UsrName              
ReqId=$4  
export ReqId

#Concurrent program parameters
p_parameter1=$5
export p_parameter1
p_parameter2=$6
export p_parameter2

#APPS Concurrent program short name
program_name="XXAD_PROGRAM_1"

echo "Beging of Execution of  program "

# +===========================================================+
# SQL Session to retrieve the Responsibility Short Name
# +===========================================================+
RESPAPPL=`sqlplus -s $OraUsr <<EOF
   set head off
   set verify off
   set feedback off
   SELECT application_short_name FROM fnd_application
   WHERE application_id = (SELECT responsibility_application_id FROM fnd_concurrent_requests where request_id=$ReqId);
   quit;
EOF`
#echo "End SQL Session"

#=============================================================
#SQL Session to retrive the Program application short name
#=============================================================
app_short_name=`sqlplus -s $OraUsr <<EOF
   set head off
   set verify off
   set feedback off
 SELECT  APPLICATION_SHORT_NAME
                   FROM fnd_application
                   WHERE application_id in ( select application_id  FROM fnd_concurrent_programs_tl
                                             where concurrent_program_id=(select concurrent_program_id from
                                             fnd_concurrent_requests where request_id=$ReqId) );
   quit;
EOF`
#echo "End SQL Session"

# +===========================================================+
# SQL Session to retrieve the Responsibility Name
# +===========================================================+
RESPNAME=`sqlplus -s $OraUsr <<EOF
   set head off
   set verify off
   set feedback off
   SELECT '"'||responsibility_name||'"' FROM fnd_responsibility_tl
   WHERE responsibility_id = (SELECT responsibility_id FROM fnd_concurrent_requests WHERE request_id=$ReqId);
   quit;
EOF`
#echo "End SQL Session"

echo "Begin of Setting Layout"

#echo "Setting Layout to get data in excel sheet"
Lay_out=`sqlplus -s $OraUsr <<EOF
   set head off
   set verify off
   set feedback off
   declare
    lb_set_layout_option boolean;
   begin
   lb_set_layout_option := apps.fnd_request.add_layout($app_short_name,$program_name,'en','US','EXCEL');
    end;
   quit;
EOF`

echo "End of Setting Layout"

echo  "Invoking the concurrent program"

OUT_CONC_SUB=`CONCSUB $OraUsr $RESPAPPL $RESPNAME $UsrName WAIT=Y CONCURRENT $app_short_name $program_name "$p_parameter1" "$p_parameter2"`

REQID1=`echo $OUT_CONC_SUB | cut -f3 -d'`

B=`echo $OUT_CONC_SUB | grep 'Completed Normal'`

if [ $? -eq 0 ]
 then
 
   echo  "Program Completed Successfully"
 
else
   echo "Program Failed. Please check the log of the request id $REQID1"
   exit 1
fi
echo "End of Execution of  program "

Workflow Tables

WF_ITEM_TYPES
The WF_ITEM_TYPES table defines an item that is transitioning through a workflow process. NAME (PK), PROTECT_LEVEL, CUSTOM_LEVEL, PERSISTENCE_TYPE

WF_ITEM_ATTRIBUTES
The WF_ITEM_ATTRIBUTES table stores definitions of attributes associated with a process. Each row includes the sequence in which the attribute is used as well as the format of the attribute data. ITEM_TYPE (PK), NAME (PK), SEQUENCE, TYPE, PROTECT_LEVEL, CUSTOM_LEVEL

WF_ACTIVITIES
WF_ACTIVITIES table stores the definition of an activity. Activities can be processes, notifications, functions or folders.ITEM_TYPE (PK), NAME (PK), VERSION(PK), TYPE, RERUN, EXPAND_ROLE, PROTECT_LEVEL, CUSTOM_LEVEL, BEGIN_DATE, RROR_ITEM_TYPE, RUNNABLE_FLAG

WF_ACTIVITY_ATTRIBUTES
The WF_ACTIVITY_ATTRIBUTES table defines attributes which behave as parameters for an activity. Activity attributes are only used by function activities.Examples of valid attribute types are DATE, DOCUMENT, FORM, ITEMATTR, LOOKUP, and VARCHAR2.
ACTIVITY_ITEM_TYPE (PK), ACTIVITY_NAME (PK), ACTIVITY_VERSION (PK), NAME (PK), SEQUENCE, TYPE, VALUE_TYPE, PROTECT_LEVEL, CUSTOM_LEVEL

WF_MESSAGES
WF_MESSAGES contains the definitions of messages which may be sent out as notifications. TYPE (PK), NAME (PK), PROTECT_LEVEL, CUSTOM_LEVEL

WF_MESSAGE_ATTRIBUTES
WF_MESSAGE_ATTRIBUTES contains message attribute definitions.

WF_NOTIFICATIONS
WF_NOTIFICATIONS holds the runtime information about a specific instance of a sent message. A new row is created in the table each time a message is sent.

WF_NOTIFICATION_ATTRIBUTES
WF_NOTIFICATION_ATTRIBUTES holds rows created for attributes of a notification. When each new notification is created, a notification attribute row is created for each message attribute in the message definition. Initially, the values of the notification attributes are set to the default values specified in the message attribute definition.

WF_ITEMS
WF_ITEMS is the runtime table for workflow processes. Each row defines one work item within the system. ITEM_TYPE (PK), ITEM_KEY (PK), ROOT_ACTIVITY, ROOT_ACTIVITY_VERSION, BEGIN_DATE

WF_ITEM_ACTIVITY_STATUSES
The WF_ITEM_ACTIVITY_STATUSES TABLE is the runtime table for a work item. Each row includes the start and end date, result code, and any error information an activity generates. ITEM_TYPE (PK), ITEM_KEY (PK), PROCESS_ACTIVITY (PK)

WF_ITEM_ACTIVITY_STATUSES_H
The WF_ITEM_ACTIVITY_STATUSES_H table stores the history of the WF_ITEM_ACTIVITY_STATUSES table. ITEM_TYPE, ITEM_KEY, PROCESS_ACTIVITY

WF_PROCESS_ACTIVITIES
WF_PROCESS_ACTIVITIES stores the data for an activity within a specific process. PROCESS_ITEM_TYPE, PROCESS_NAME, PROCESS_VERSION, ACTIVITY_ITEM_TYPE, ACTIVITY_NAME, INSTANCE_ID (PK), INSTANCE_LABEL, PERFORM_ROLE_TYPE, PROTECT_LEVEL, CUSTOM_LEVEL

WF_ACTIVITY_TRANSITIONS
The WF_ACTIVITY_TRANSITIONS table defines the transitions from one activity to another in a process. Each row includes the activities at the beginning and end of the transition, as well as the result code and physical location of the transition in the process window. FROM_PROCESS_ACTIVITY (PK), RESULT_CODE (PK), TO_PROCESS_ACTIVITY (PK), PROTECT_LEVEL,CUSTOM_LEVEL

WF_ACTIVITY_ATTR_VALUES
The WF_ACTIVITY_ATTR_VALUES table contains the data for the activity attributes. Each row includes the process activity id and the associated value for the attribute. PROCESS_ACTIVITY_ID (PK), NAME (PK), VALUE_TYPE, PROTECT_LEVEL, CUSTOM_LEVEL


Thursday, April 25, 2013

Query to get Responsibilities Assigned with Particular Function

SELECT r.responsibility_name
  FROM fnd_responsibility_vl r, fnd_form_functions f
 WHERE f.function_name = < Function_Name>
   AND r.menu_id IN (SELECT     me.menu_id
                           FROM fnd_menu_entries me
                     START WITH me.function_id = f.function_id
                     CONNECT BY PRIOR me.menu_id = me.sub_menu_id)
   AND r.menu_id NOT IN (
                       SELECT frf.action_id
                         FROM fnd_resp_functions frf
                        WHERE frf.action_id = r.menu_id
                              AND frf.rule_type = 'M')
   AND f.function_id NOT IN (
                   SELECT frf.action_id
                     FROM fnd_resp_functions frf
                    WHERE frf.action_id = f.function_id

                          AND frf.rule_type = 'F');