Sunday, 15 April 2012

Dynamically Execute SQL statement stored in CLOB field with bind variables

 

  I saw many examples in the past when SQL statement was actually stored in CLOB field and programmer had to execute the statement dynamically.

All Oracle PL/SQL developers are familiar with “execute immediate” statement, but unfortunately  it cannot use CLOB field as an input.

But it is not the only way to execute the code dynamically.  Oracle also provides DBMS_SQL package that can execute the code dynamically and it can get the statement as an array data type. We will use it

   Here how you can do it.

Let assume that your SQL will be stored in the following variable

l_stmt         CLOB;

Now we need to split the CLOB to chunks that will became a member of array I mentioned previously

v_upperbound NUMBER;

This is array definition

v_sql        DBMS_SQL.VARCHAR2S;

Calculate array length

v_upperbound := CEIL(DBMS_LOB.GETLENGTH(l_stmt)/256);

Fill array members:

FOR i IN 1..v_upperbound
LOOP
         v_sql(i) := DBMS_LOB.SUBSTR(l_stmt
                                  ,256 -- amount
                                  ,((i-1)*256)+1 -- offset
                                  );
END LOOP;

 

Create new cursor:

v_cur        INTEGER;

v_cur := DBMS_SQL.OPEN_CURSOR;

 

Prepare your statement for execution , but parsing array members

DBMS_SQL.PARSE(v_cur, v_sql, 1, v_upperbound, FALSE, DBMS_SQL.NATIVE);

You can also use bind variables at this point

dbms_sql.bind_variable( v_cur, ':USER_NAME', ‘SYSADMIN’);

All what is left is to execute the statement

v_ret        NUMBER;

v_ret := DBMS_SQL.EXECUTE(v_cur);

 

Bellow if full example that uses approach described above

declare

l_stmt CLOB;
v_upperbound NUMBER;
v_cur INTEGER;
v_sql DBMS_SQL.VARCHAR2S;
v_ret NUMBER;

begin
-- get sql statement into CLOB
select statement
into l_stmt
from XX_NEW_STATEMENTS_V --some view that holds CLOB
--with SQL
where statement_type = 'SETUP'
and seq_num = 10;

v_upperbound := CEIL(DBMS_LOB.GETLENGTH(l_stmt) / 256);

FOR i IN 1 .. v_upperbound LOOP
v_sql(i) := DBMS_LOB.SUBSTR(l_stmt, -- clob statement
256, -- amount
((i - 1) * 256) + 1
);
END LOOP;

v_cur := DBMS_SQL.OPEN_CURSOR;
-- parse sql statement
DBMS_SQL.PARSE(v_cur, v_sql, 1, v_upperbound, FALSE, DBMS_SQL.NATIVE);
-- use bind variable if you need
dbms_sql.bind_variable(v_cur, ':USER_ID', 235341);
-- execute
v_ret := DBMS_SQL.EXECUTE(v_cur);

end;

Tuesday, 27 September 2011

Get connection to APPS schema without knowing APPS password in EBS

 

First of all I need to explain that this post will not explain how to get the APPS password , but will explain how to obtain JDBC connection object.

   Each one who ever developed Oracle Framework page knows that you don’t really need to specify APPS password to work with EBS. But you do need to specify location of dbc file. Why? Because there is an option to get “Connection” object by using dbc file.

   First of all how do you know what dbc file to use?

dbc name can be obtained from the profile called  “Applications Database ID” (APPS_DATABASE_ID). You can get it from EBS  profile directly or by using:

select fnd_profile.VALUE('APPS_DATABASE_ID') from dual

Lets call the value of profile DBC_VALUE.

So , the location of dbc file will be $FND_SECURE/DBC_VALUE.dbc

Now , when you know the location of dbc file we can obtain JDBC connection.

We will use the following code:

 

import java.sql.*;

//this classes located under $OA_JAVA in EBS
import oracle.apps.fnd.common.AppsContext;
import oracle.apps.fnd.common.VersionInfo;

public class GetConnection
{
public GetConnection(String dbcFileLocation)
{
AppsContext ac
= new AppsContext(pDbcFile);
Connection sConn
= ac.getJDBCConnection();
}
//do whatever you want after you get Connection
}

The connection object that you get connected to , is APPS user. From this point you can do whatever operation with database that APPS user is privileged to do