2.8 Remote User-defined Function Support
User-defined functions in a remote non-Oracle database can be used in SQL statements.
- Return Values and Stored Procedures
By default, all stored procedures and functions do not return a return value to the user. - Result Sets and Stored Procedures
The Oracle Database Gateway for SQL Server provides support for stored procedures which return result sets.
See Also:
Oracle Database Heterogeneous Connectivity User's Guide for more information about executing user-defined functions on a non-Oracle database.Parent topic: SQL Server Gateway Features and Restriction
2.8.1 Return Values and Stored Procedures
By default, all stored procedures and functions do not return a return value to the user.
To enable return values, set the HS_FDS_PROC_IS_FUNC
parameter value to TRUE
.
See Also:
Initialization Parameters for information about both editing the initialization parameter file and theHS_FDS_PROC_IS_FUNC
parameter.
Note:
If you set theHS_FDS_PROC_IS_FUNC
gateway initialization parameter to TRUE
, you must change the syntax of the procedure execute statement for all existing stored procedures.
In the following example, the employee name JOHN SMYTHE
is passed to the SQL Server stored procedure REVISE_SALARY
. The stored procedure retrieves the salary value from the SQL Server database to calculate a new yearly salary for JOHN SMYTHE
. The revised salary returned in RESULT
is used to update EMP
in a table of an Oracle database:
DECLARE INPUT VARCHAR2(15); RESULT NUMBER(8,2); BEGIN INPUT := 'JOHN SMYTHE'; RESULT := REVISE_SALARY@MSQL(INPUT); UPDATE EMP SET SAL = RESULT WHERE ENAME =: INPUT; END; /
The procedural feature automatically converts non-Oracle data types to and from PL/SQL data types.
Parent topic: Remote User-defined Function Support
2.8.2 Result Sets and Stored Procedures
The Oracle Database Gateway for SQL Server provides support for stored procedures which return result sets.
By default, all stored procedures and functions do not return a result set to the user. To enable result sets, set the HS_FDS_RESULTSET_SUPPORT
parameter value to TRUE
.
See Also:
Initialization Parameters for information about both editing the initialization parameter file and theHS_FDS_RESULTSET_SUPPORT
parameter. For further information about Oracle support for result sets in non-Oracle databases see Oracle Database Heterogeneous Connectivity User's Guide.
Note:
If you set theHS_FDS_RESULTSET_SUPPORT
gateway initialization parameter to TRUE
, then you must change the syntax of the procedure execute statement for all existing stored procedures, else errors will occur.
When accessing stored procedures with result sets through the Oracle Database Gateway for SQL Server, you will be in the sequential mode of Heterogeneous Services.
The Oracle Database Gateway for SQL Server returns the following information to Heterogeneous Services during procedure description:
- All the input arguments of the remote stored procedure
- None of the output arguments
- One out argument of type ref cursor (corresponding to the first result set returned by the stored procedure)
Client programs have to use the virtual package function DBMS_HS_RESULT_SET.GET_NEXT_RESULT_SET
to get the ref cursor for subsequent result sets. The last result set returned is the out argument from the procedure.
The limitations of accessing result sets are the following:
- Result sets returned by a remote stored procedure have to be retrieved in the order in which they were placed on the wire
- On execution of a stored procedure, all result sets returned by a previously executed stored procedure will be closed (regardless of whether the data has been completely retrieved or not)
In the following example, the SQL Server stored procedure is executed to fetch the contents of the emp
and dept
tables from SQL Server:
create procedure REFCURPROC (@arg1 varchar(255), @arg2 varchar(255) output) as select @arg2 = @arg1 select * from EMP select * from DEPT go
This stored procedure assigns the input parameter arg1 to the output parameter arg2, opens the query SELECT * FROM EMP
in ref cursor rc1, and opens the query SELECT * FROM DEPT
in ref cursor rc2.
- OCI Program Fetching from Result Sets in Sequential Mode
The following example shows OCI program fetching from result sets in sequential mode. - PL/SQL Program Fetching from Result Sets in Sequential Mode
Example of a PL/SQL program fetching from results sets in sequential mode.
Parent topic: Remote User-defined Function Support
2.8.2.1 OCI Program Fetching from Result Sets in Sequential Mode
The following example shows OCI program fetching from result sets in sequential mode.
OCIEnv *ENVH; OCISvcCtx *SVCH; OCIStmt *STMH; OCIError *ERRH; OCIBind *BNDH[3]; OraText arg1[20]; OraText arg2[255]; OCIResult *rset; OCIStmt *rstmt; ub2 rcode[3]; ub2 rlens[3]; sb2 inds[3]; OraText *stmt = (OraText *) "begin refcurproc@MSQL(:1,:2,:3); end;"; OraText *n_rs_stm = (OraText *) "begin :ret := DBMS_HS_RESULT_SET.GET_NEXT_RESULT_SET@MSQL; end;"; /* Prepare procedure call statement */ /* Handle Initialization code skipped */ OCIStmtPrepare(STMH, ERRH, stmt, strlen(stmt), OCI_NTV_SYNTAX, OCI_DEFAULT); /* Bind procedure arguments */ inds[0] = 0; strcpy((char *) arg1, "Hello World"); rlens[0] = strlen(arg1); OCIBindByPos(STMH, &BNDH[0], ERRH, 1, (dvoid *) arg1, 20, SQLT_CHR, (dvoid *) &(inds[0]), &(rlens[0]), &(rcode[0]), 0, (ub4 *) 0, OCI_DEFAULT); inds[1] = -1; OCIBindByPos(STMH, &BNDH[1], ERRH, 1, (dvoid *) arg2, 20, SQLT_CHR, (dvoid *) &(inds[1]), &(rlens[1]), &(rcode[1]), 0, (ub4 *) 0, OCI_DEFAULT); inds[2] = 0; rlens[2] = 0; OCIDescriptorAlloc(ENVH, (dvoid **) &rset, OCI_DTYPE_RSET, 0, (dvoid **) 0); OCIBindByPos(STMH, &BNDH[2], ERRH, 2, (dvoid *) rset, 0, SQLT_RSET, (dvoid *) &(inds[2]), &(rlens[2]), &(rcode[2]), 0, (ub4 *) 0, OCI_DEFAULT); /* Execute procedure */ OCIStmtExecute(SVCH, STMH, ERRH, 1, 0, (CONST OCISnapshot *) 0, (OCISnapshot *) 0, OCI_DEFAULT); /* Convert result set to statement handle */ OCIResultSetToStmt(rset, ERRH); rstmt = (OCIStmt *) rset; /* After this the user can fetch from rstmt */ /* Issue get_next_result_set call to get handle to next_result set */ /* Prepare Get next result set procedure call */ OCIStmtPrepare(STMH, ERRH, n_rs_stm, strlen(n_rs_stm), OCI_NTV_SYNTAX, OCI_DEFAULT); /* Bind return value */ OCIBindByPos(STMH, &BNDH[1], ERRH, 1, (dvoid *) rset, 0, SQLT_RSET, (dvoid *) &(inds[1]), &(rlens[1]), &(rcode[1]), 0, (ub4 *) 0, OCI_DEFAULT); /* Execute statement to get next result set*/ OCIStmtExecute(SVCH, STMH, ERRH, 1, 0, (CONST OCISnapshot *) 0, (OCISnapshot *) 0, OCI_DEFAULT); /* Convert next result set to statement handle */ OCIResultSetToStmt(rset, ERRH); rstmt = (OCIStmt *) rset; /* Now rstmt will point to the second result set returned by the remote stored procedure */ /* Repeat execution of get_next_result_set to get the output arguments */
Parent topic: Result Sets and Stored Procedures
2.8.2.2 PL/SQL Program Fetching from Result Sets in Sequential Mode
Example of a PL/SQL program fetching from results sets in sequential mode.
Assume that the table loc_emp
is a local table exactly like the SQL Server emp
table. The same assumption applies for loc_dept
. The table outargs
has columns corresponding to the out
arguments of the SQL Server stored procedure.
create table outargs (outarg varchar2(255), retval number);
create or replace package rcpackage is type RCTYPE is ref cursor; end rcpackage; /
declare rc1 rcpackage.rctype; rec1 loc_emp%rowtype; rc2 rcpackage.rctype; rec2 loc_dept%rowtype; rc3 rcpackage.rctype; rec3 outargs%rowtype; out_arg varchar2(255); begin -- Execute procedure out_arg := null; refcurproc@MSQL('Hello World', out_arg, rc1); -- Fetch 20 rows from the remote emp table and insert them into loc_emp for i in 1 .. 20 loop fetch rc1 into rec1; insert into loc_emp (rec1.empno, rec1.ename, rec1.job, rec1.mgr, rec1.hiredate, rec1.sal, rec1.comm, rec1.deptno); end loop; -- Close ref cursor close rc1; -- Get the next result set returned by the stored procedure rc2 := dbms_hs_result_set.get_next_result_set@MSQL; -- Fetch 5 rows from the remote dept table and insert them into loc_dept for i in 1 .. 5 loop fetch rc2 into rec2; insert into loc_dept values (rec2.deptno, rec2.dname, rec2.loc); end loop; --Close ref cursor close rc2; -- Get the output arguments from the remote stored procedure -- Since we are in sequential mode, they will be returned in the -- form of a result set rc3 := dbms_hs_result_set.get_next_result_set@MSQL; -- Fetch them and insert them into the outargs table fetch rc3 into rec3; insert into outargs (rec3.outarg, rec3.retval); -- Close ref cursor close rc3; end; /
Parent topic: Result Sets and Stored Procedures