Integration through procedure Oracle - stored-procedures

I would like to integrate with OSB keeping my logic in the DB. To minimize bandwidth load and calls to DB I would like to batch insert records through a Stored Procedure.
my goal -> avoid loops on procedure, avoid cursor, avoid multi call to DB.
In TSQL I would have done this through Table type parameter, but as this is not possible in PLSQL I have created the following script that gives me error on parameter select in the package body. Can anyone help me?:
--create type object
create or replace TYPE "Type_test" IS OBJECT (
id number(20,0)
oppdateringstype VARCHAR2(50)
)
;
-- Create package head
create or replace package test as
type t_input_table is table of Type_test index by binary_integer;
procedure Proc (p_input_table in t_input_table);
end;
--Create package body
create or replace package body test as
procedure Proc(p_input_table in t_input_table)
as
BEGIN
--Some logic select * from p_input_table
end;

Related

Is there anyway to run multiple-procedures back-to-back in PL/SQL so that a table is created and then filled in as structured in my code?

I am working with Oracle SQL Developer and I am trying get the below code to work and just can't figure it out. I have tried multiple different methods including implementing for loops, execute immediate's, scheduling and recompiling.
BEGIN
ORDER_STATUS_1_DROP_TABLE; -- If the table exist, drop it
ORDER_STATUS_2_CREATE_TABLE; -- Create the table
GRANT_NEWANALYTICS; -- Grant users select access
ORDER_STATUS_3_SCRIPT; -- Run script to insert data into table
END;
What the code is trying to do is this:
Procedure 1: Drop if exist, otherwise skip. I don't want to see any warning errors stating that no table exist if this procedure is run when there is no table. This procedure by itself does work as intended.
create or replace PROCEDURE ORDER_STATUS_1_DROP_TABLE IS
table_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_does_not_exist, -942);
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE <Table Name>';
EXCEPTION
WHEN table_does_not_exist then
dbms_output.put_line( 'table dose not exist');
END ORDER_STATUS_1_DROP_TABLE;
Procedure 2: Once the table is dropped, this procedure recreates it with the correct . I don't want to see any errors for "this table already exist" and that is why, in part, procedure 1 exists. This by itself works as intended.
create or replace PROCEDURE ORDER_STATUS_2_CREATE_TABLE IS
v_sql LONG;
BEGIN
v_sql:= 'create table <Table Name>
(<parameters>)';
EXECUTE IMMEDIATE v_sql;
END ORDER_STATUS_2_CREATE_TABLE;
Procedure 3: This just gives users select access to the table created in the last procedure. This procedure works as it was intended.
create or replace PROCEDURE GRANT_NEWANALYTICS IS
BEGIN
EXECUTE IMMEDIATE
'GRANT SELECT ON <Table Name> TO <UserID>';
END;
Procedure 4: This is a complicated query. It is an insert select all from (table left join to a few other tables based upon fields and conditions, etc). After procedures 1-3 are run, this procedure by itself has not issue running, but by itself.
create or replace PROCEDURE ORDER_STATUS_3_SCRIPT IS
BEGIN
DELETE FROM <Table Name>;
INSERT INTO <Table Name>
SELECT * FROM(<Multiple Table Joins>);
END ORDER_STATUS_3_SCRIPT;
When I run the procedures like this:
BEGIN
ORDER_STATUS_1_DROP_TABLE; -- If the table exist, drop it
ORDER_STATUS_2_CREATE_TABLE; -- Create the table
GRANT_NEWANALYTICS; -- Grant users select access
ORDER_STATUS_3_SCRIPT; -- Run script to insert data into table
END;
I get the following error report:
Error report -
ORA-04068: existing state of packages has been discarded
ORA-04065: not executed, altered or dropped stored procedure "<user>.ORDER_STATUS_3_SCRIPT"
ORA-06508: PL/SQL: could not find program unit being called: "<user>.ORDER_STATUS_3_SCRIPT"
ORA-06512: at line 5
04068. 00000 - "existing state of packages%s%s%s has been discarded"
*Cause: One of errors 4060 - 4067 when attempt to execute a stored procedure.
*Action: Try again after proper re-initialization of any application's state.
Now, If I run these separately, it works. So if I first run this:
BEGIN
ORDER_STATUS_1_DROP_TABLE; -- If the table exist, drop it
ORDER_STATUS_2_CREATE_TABLE; -- Create the table
GRANT_NEWANALYTICS; -- Grant users select access
END;
<OUTPUT> PL/SQL procedure successfully completed.
And then this:
BEGIN
ORDER_STATUS_3_SCRIPT; -- Run script to insert data into table
END;
<OUTPUT> <Query runs>
I have not issues. I want to run these set of procedures in ones sweep and could use some help on the idea of such. Anyone have any ideas?
If you want to run all these procedures as a part of a single PL/SQL block then every reference to your table would need to be via dynamic SQL. So ORDER_STATUS_3_SCRIPT would need to use dynamic SQL to build the insert statement(s) to populate the table rather than using simple static SQL. That's obviously possible but it does increase the complexity of the script. Potentially substantially.
Having two PL/SQL blocks, which you've demonstrated works, seems much simpler.

How to get the restult table of a stored procedure into a temp table?

Enviroment:
DB2 Version 11.1,
OS - Linux
How to get the result table of stored procedure into a temp table?
The table and the result have the same table configuration (firstColumn int, secondColumn nvarchar(255))
I'm assuming your stored procedure returns an open cursor, so you want to consume that cursor, inserting its contents into a session table (declared global temporary table) on Db2-LUW.
In addition to fetch and insert statements, you need to understand the following statements:
associate result set locator ... with procedure ...
allocate ... cursor for result set ...
Here is a deliberately artificial example of a nested stored procedure, which shows fetching a result-set from a nested procedure into a session table. The purpose is to show how the syntax works, rather than to do anything useful with data (as the net effect can be equally met by a simple catalog query in this case). This example can be run at the Db2 command-line (for example at the bash shell, after you connected to a database with appropriate permissions):
update command options using s on ;
--#SET TERMINATOR #
create or replace procedure alltabs
dynamic result sets 1
language sql
specific alltabs
begin
declare v_cur cursor with return to caller for select tabschema,tabname,type from syscat.tables ;
open v_cur;
end#
declare global temporary table session.thetables(tabschema varchar(128), tabname varchar(128))
not logged with replace on commit preserve rows #
create or replace procedure populate_dgtt()
language sql
specific populate_dgtt
begin
declare v_rs result_set_locator varying;
declare v_tabschema varchar(128);
declare v_tabname varchar(128);
declare v_type char(1);
declare sqlstate char(5) default '00000';
call alltabs;
associate result set locator (v_rs) with procedure alltabs;
allocate v_rscur cursor for result set v_rs;
fetch from v_rscur into v_tabschema, v_tabname, v_type;
while ( sqlstate = '00000') do
if v_type='V' and v_tabschema='SYSSTAT'
then
insert into session.thetables(tabschema,tabname) values (v_tabschema, v_tabname);
end if;
fetch from v_rscur into v_tabschema, v_tabname, v_type;
end while;
return;
end#
call populate_dgtt()#
select rtrim(Tabschema)||'.'||rtrim(tabname) from session.thetables #

DB2 SQL procedure - Calling initiate procedure before declaration

I am making an sql procedure (in lib EXTLIB) that will be called from an external system using JDBC. We have a user, EXTUSER, that is used for running all requests coming from there. The problem is that this user can only have a single starting library, which in our case is EXTLIB (if anyone knows how to add more, please do tell me and become a hero in my company). We have a procedure initiate that initiates the environment (i.e. adds all necessary libs to LIBL). This needs to be called at the start of all procedures in EXTLIB.
My procedure needs to fetch data from a view in our internal lib: INTERLIB. The problem is that we are using ARCAD for version/release/everything management, and ARCAD doesn't like qualifiers, so it automatically removes them, meaning that the declaration at the start can't find the view in INTERLIB, and thus it stops before reaching the initate call.
I need a way to run the call before the declaration, while retaining the functionality. I'm also open to any other alternative solutions. The only one I can think of is instead coding it in RPG, but we have a lot of simple procedures for which that would just be a waste of time. manually creating the procedure in STRSQL is not an option, because when ARCAD transfers a version to production it will recompile everything, thus removing any manual qualifiers we have put there.
Here's the code:
CREATE PROCEDURE MyProcedure ()
LANGUAGE SQL
SPECIFIC MYFILE
CALLED ON NULL INPUT
DYNAMIC RESULT SETS 1
BEGIN
declare c1 cursor with return to client for
select
id,
required
from INTERLIB.cus_CustomerPurpose_v3_0
call INITIATE();
open c1;
call DEINITIATE();
END;
I think you have two options:
1) To create an internal block in the stored procedure,
CREATE PROCEDURE MyProcedure ()
LANGUAGE SQL
SPECIFIC MYFILE
CALLED ON NULL INPUT
DYNAMIC RESULT SETS 1
BEGIN
call INITIATE();
BEGIN
declare c1 cursor with return to client for
select
id,
required
from INTERLIB.cus_CustomerPurpose_v3_0;
open c1;
END;
call DEINITIATE();
END #
2) To call another stored procedure
CREATE PROCEDURE MyProcedure ()
LANGUAGE SQL
SPECIFIC MYFILE
CALLED ON NULL INPUT
DYNAMIC RESULT SETS 1
BEGIN
call INITIATE();
call another_SP();
call DEINITIATE();
END #

How to define an Array of values (or a Column) into a Procedure Argument?

I am working on a Netezza SP and is stuck with a problem.
I have a SP, defined as say:
CREATE OR REPLACE PROCEDURE MY_PROC(VARCHAR(ANY)) RETURNS INTEGER LANGUAGE NZPLSQL
AS
BEGIN_PROC
DECLARE
v_temp ALIAS FOR $1;
/* Other decalarations */
result_ts INTEGER;
BEGIN
result_ts := 0;
/* Procedure Body */
RETURN result_ts;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Exception Raised: %', SQLERRM;
END;
END_PROC;
If I am running this SP with one value, such as:
SELECT MY_PROC('TEST_INPUT');
But if I am trying to run it with a column value, such as:
SELECT MY_PROC(TEST_COLUMN) FROM TEST_TABLE;
Its giving me error as:
ERROR: Can't use a stored procedure in this context
I know that in the second scenario I am passing an Array (i guess) but this is not what the Procedure has expected.
Now I am trying to have a procedure that can accept these kind of values but could not succeeded so far, LOOPing and all I have taken care but only problem is the Argument which I don't know how to pass.
Any help would be appreciated, let me know if I need to provide any extra info on this.
Asif
Stored procedures in Netezza, as of v7.2, can only be called in the following ways, as documented here.
CALL sproc_name(...);
EXEC sproc_name(...);
SELECT sproc_name(...);
Note that the SELECT form does not allow a FROM clause.
If you want the stored procedure to act on a particular column from a particular table that changes from invocation to invocation, you could pass the names of those as arguments to the stored procedure and have the entirety of the SQL logic encoded within. You could even pass arbitrary code into the stored procedure to build a query internally.
The way you are trying to call it now is more like calling a user defined function, and that simply won't work with stored procedures here.

db2 from procedure run file

using IBM DB2 i would like to create a procedure that in case a table does not exist goes to file and start with create and insert statements written in that file. I cannot put all statements inside a procedure because there is just too many of them
my semi-pseudo code so far is
CREATE PROCEDURE KLEMENTEST.create_table
()
LANGUAGE SQL
begin atomic
if (not exists(select 'A' from syscat.tables where tabschema = 'TESTSCHEMA' and tabname='TESTTABLE')) then
--- run queries from file located in "c:\path\to\file.txt"
end if
end ;
any suggestions ??
thank you
There are several options:
1) Create an external stored procedure in Java or C that will execute the command that you want. For example
db2 -tf file.sql
Remember to execute DB2 with a profile (. db2profile). You will call this stored procedure after having test that the table does not exist.
2) Create the stored procedure, and read the content of the file that contains the ddl, then with the content, you create a dynamic SQL. You can read files via UTL_FILE module. However, this module is not available in Express-C edition. http://publib.boulder.ibm.com/infocenter/db2luw/v10r1/topic/com.ibm.db2.luw.apdv.sqlpl.doc/doc/r0053689.html
The general problem of this approach is the location of the file to "execute" in the file system, and also the stored procedure becomes platform dependent.

Resources