The package Body is giving Compilation errors.I don't know why.Please help me out - plsql-package

The package is created is sucessfully. But when it comes to Package body it gives "Package body created with compilation error".But there are no error that i can see.
The error is like
ORA-04063: package body "VENDORDB.P_ENLD0055_VA" has errors
ORA-06508: PL/SQL: could not find program unit being called: "VENDORDB.P_ENLD0055_VA"
I tried giving grant excess to user and for updating the database but still the error is not resolving
create or replace package vendordb.p_enld0055_va is
PROCEDURE sp_group_id_update(p_batch_id NUMBER,
p_file_name VARCHAR2,
p_group_id VARCHAR2);
end p_enld0055_va;
/
create or replace package body vendordb.p_enld0055_va is
PROCEDURE sp_group_id_update(p_batch_id NUMBER,
p_file_name VARCHAR2,
p_group_id VARCHAR2) is
v_batch_id VARCHAR2(100) := p_batch_id;
v_file_name VARCHAR2(100) := p_file_name;
v_group_id VARCHAR2(100) := p_group_id;
type t_TBL_row_ID IS TABLE OF ROWID;
v_row_ID t_TBL_row_ID;
cursor CUR_PPL is
select
h.rowid
from VENDORDB.CLAIM_PROF_HDR h
where batch_id = v_batch_id ;
Begin
open CUR_PPL;
loop
fetch CUR_PPL
bulk collect into v_row_ID
limit 1000
;
exit when v_row_ID.count()=0;
forall i in 1 .. v_row_ID.count()
UPDATE VENDORDB.CLAIM_PROF_HDR h
SET group_id = CASE
WHEN EXISTS (select file_name from
nemis.file_control where batch_id = v_batch_id and file_name like
v_file_name) THEN v_group_id
ELSE NULL
END
where h.rowid = v_row_ID(i);
commit;
end loop;
close CUR_PPL ;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('UNEXPECTED ERROR OCCURED');
ROLLBACK;
end;
end p_enld0055_va;
/

Related

Assistance needed for a first timer in package creation

This is going to be a difficult question to get answered which is why for 3 days that I have worked on this package (my first package ever) I have been hesitant to ask.
Below is the layout for the spec and body of my package. Before you look at that here is what I am trying to accomplish. I AM CLOSE TO FINISHING so there is no need to fear that this question is not worth your time.
You may see a few of my personal notes to self in the code as well.
My code is incomplete and currently isn't compiling but before it ceased to compile I can tell you it did not work either. The DROP and CREATE procedures work. NO NEED TO TOUCH THOSE. My main issues are the LOG_PROC, my EXCEPTIONS, my ARCHIVE_ALL_TABLES... as far as I know
Here is what I am trying to do:
Create a package that could be used to ‘archive’ the newly created tables into archive tables in the format “TEST_TABLE_A_13AUG2012”. This package will use a view I created called VW_TEST_TABLES which has this data:
TEST_TABLE_A
TEST_TABLE_B
TEST_TABLE_C
TEST_TABLE_D
This package will need to drop all previously archived tables before it creates new ones. As such, my package will need to have both DROP_ARCHIVE_TABLES and CREATE_ARCHIVE_TABLES procedures within it. In addition to the DROP and CREATE procedures, my package has a main procedure, called ARCHIVE_ALL_TABLES. This is the procedure that would need to be called (for instance by the scheduler) and do the actual archiving. I need to incorporate proper exception handling in these procedures. (e.g. don’t care if the table does not exist when I go to drop it).
Finally, in order to properly track each archival run, I want to build a logging mechanism. To accomplish this, I built a table in my schema called TEST_PACKAGE_LOG_TBL. This table should has the following columns: ARCHIVE_DATE (DATE), TABLE_NAME (VARCHAR2(30)), STATUS_CODE(VARCHAR2(1)), COMMENTS (VARCHAR2(4000)). For each table I archive, I want to log the date, the table name, either ‘S’ for success or ‘E’ for error and, if I encounter an error in the drop or creation of the table, what the SQLERRM was should be displayed.
Finally, my ARCHIVE_ALL_TABLES procedure should check this log table when it is finishing in order to determine if any tables were not archived properly. I created a function ERRORS_FOUND (return boolean) that accepts one IN parameter (today’s date) and checks the log table for errors. If this function returns true, my ARCHIVE_ALL_TABLES procedure should account for this and ‘notify an administrator’ (For now I am leaving this untouched but eventually it will simply account for this with a comment stating that I would notify an admin and place NULL; in the if then end block.)
To summarize, my package structure must contain (at minimum) the following procedures:
ARCHIVE_ALL_TABLES,
DROP_ARCHIVE_TABLE,
CREATE_ARCHIVE_TABLE,
ERRORS_FOUND (function)
--package specification
CREATE OR REPLACE PACKAGE PKG_TEST_TABLES IS
-- Author :
-- Created : 8/14/2012 8:40:18 AM
-- Purpose : For storing procedures to drop, create, and archive new tables
/* Package specification*/
PROCEDURE ARCHIVE_ALL_TABLES;
PROCEDURE DROP_ARCHIVE_TABLES; --2nd
PROCEDURE CREATE_ARCHIVE_TABLES; --1st and call both from archive tables first assuming it works
PROCEDURE LOG_PROC
(
P_PROCESS_START_TIMESTAMP TIMESTAMP
,P_ARCHIVE_DATE DATE
,P_TABLE_NAME VARCHAR2
,P_STATUS_CODE VARCHAR2
,P_COMMENTS VARCHAR2
);
PROCEDURE W(STR VARCHAR2);
FUNCTION ERRORS_FOUND(P_JOB_RUN_TIMESTAMP TIMESTAMP) RETURN BOOLEAN;
END PKG_TEST_TABLES;
--package body
CREATE OR REPLACE PACKAGE BODY PKG_TEST_TABLES IS
/* Package body*/
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
/* Procedure 'W' is a wrapper for DBMS output. Placed at top of package to make globally available*/
PROCEDURE W(STR VARCHAR2) IS
L_STRING VARCHAR2(4000);
BEGIN
L_STRING := STR;
DBMS_OUTPUT.PUT_LINE(STR);
END;
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
PROCEDURE DROP_ARCHIVE_TABLES AS
/* Purpose: For dropping previously archived tables so that new ones can be created */
L_NO_TABLES_TO_DROP EXCEPTION;
BEGIN
/* Will drop previously archived tables not current ones*/
FOR STMT IN (SELECT 'DROP TABLE mySchema.' || TABLE_NAME AS STR
FROM VW_TEST_TABLES
WHERE REGEXP_LIKE(TABLE_NAME, '.+[0...9]'))
LOOP
EXECUTE IMMEDIATE STMT.STR; --so that I don't need ';' at the end of each dynamically created SQL
END LOOP;
W('Done'); --put the W back in here when in package scope
EXCEPTION
WHEN L_NO_TABLES_TO_DROP THEN
NULL;
END;
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
PROCEDURE CREATE_ARCHIVE_TABLES AS
/* purpose: setting variable to equal the creation of my 4 tables. Recreating the archive tables */
L_NO_TABLES_TO_CREATE EXCEPTION;
L_TABLES_NOT_SUCCESSFULLY_CREATED EXCEPTION;
BEGIN
FOR STMT IN (SELECT 'CREATE TABLE ' || TABLE_NAME || '_' || TO_CHAR(SYSDATE, 'ddMONyyyy') || ' AS SELECT * FROM ' || TABLE_NAME AS STR
FROM VW_TEST_TABLES)
--LOG_PROC( ,TO_CHAR(SYSDATE, 'ddMONyyyy') , TABLE_NAME ,'E' ,'TABLE ARCHIVED SUCCESSFULLY')
LOOP
--DBMS_OUTPUT.PUT_LINE(STMT.STR); --want to do a dbms output first before using 'execute immediate'. Hit test, and run it
EXECUTE IMMEDIATE STMT.STR; --so that I don't need ';' at the end of each dynamically created SQL
END LOOP;
-- DBMS_OUTPUT.PUT_LINE('Done'); --put the W back in here when in package scope
EXCEPTION
WHEN L_NO_TABLES_TO_CREATE THEN
NULL; --logging can go here
--can call logging procedure here for dml don't need execute immediate, just use insert into
WHEN L_TABLES_NOT_SUCCESSFULLY_CREATED THEN
NULL; --W('ERROR: ' || SQLERRM);
END;
--PROCEDURE IS NOT CREATING TABLES YET
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
PROCEDURE LOG_PROC(P_PROCESS_START_TIMESTAMP TIMESTAMP, P_ARCHIVE_DATE DATE, P_TABLE_NAME VARCHAR2, P_STATUS_CODE VARCHAR2, P_COMMENTS VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
/* variables */
L_PROCESS_START_TIMESTAMP TIMESTAMP; L_ARCHIVE_DATE DATE; L_TABLE_NAME VARCHAR2(4000); L_STATUS_CODE VARCHAR2(1); L_COMMENTS VARCHAR2(4000);
BEGIN
L_PROCESS_START_TIMESTAMP := P_PROCESS_START_TIMESTAMP; L_ARCHIVE_DATE := P_ARCHIVE_DATE; L_TABLE_NAME := P_TABLE_NAME; L_STATUS_CODE := P_STATUS_CODE; L_COMMENTS := P_COMMENTS;
INSERT INTO TEST_PACKAGE_LOG_TBL(PROCESS_START_TIMESTAMP, ARCHIVE_DATE, TABLE_NAME, STATUS_CODE, COMMENTS) VALUES(L_PROCESS_START_TIMESTAMP, L_ARCHIVE_DATE, L_TABLE_NAME, L_STATUS_CODE, L_COMMENTS);
RETURN;
END;
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
FUNCTION ERRORS_FOUND(P_JOB_RUN_TIMESTAMP TIMESTAMP) RETURN BOOLEAN IS
L_JOB_RUN_TIMESTAMP TIMESTAMP; ERROR_COUNT NUMBER; ERROR_BOOL BOOLEAN;
BEGIN
L_JOB_RUN_TIMESTAMP := P_JOB_RUN_TIMESTAMP;
SELECT COUNT(*) INTO ERROR_COUNT FROM TEST_PACKAGE_LOG_TBL WHERE STATUS_CODE = 'E' AND PROCESS_START_TIMESTAMP = L_JOB_RUN_TIMESTAMP; IF ERROR_COUNT > 0 THEN ERROR_BOOL := TRUE; ELSE ERROR_BOOL := FALSE;
END IF;
RETURN ERROR_BOOL;
END;
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
PROCEDURE ARCHIVE_ALL_TABLES AS
/*
Original Author:
Created Date: 13-Aug-2012
Purpose: To drop all tables before recreating and archiving newly created tables
NOTE: in package - do not use create or replace and 'as' would be alternative to 'is'
*/
/*variables*/
L_DROP_ARCHIVE_TABLES VARCHAR2(4000); L_SQL_CREATE_ARCHIVED_TABLES VARCHAR2(4000); L_PREVENT_SQL_INJECTION
EXCEPTION
;
--L_NOTIFY_ADMINISTRATOR VARCHAR(4000); --TO BE DONE AT A LATER TIME
BEGIN
RETURN;
EXCEPTION
WHEN L_PREVENT_SQL_INJECTION THEN NULL;
WHEN OTHERS THEN W('ERROR: ' || SQLERRM);
END;
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------
BEGIN
-- Initialization
/*archive all tables is like my 'driver' that calls drop then create while logging to the table. Pragma_auto prevents a rollback which would prevent table logging
FIRST: This package will need to drop all previously archived tables before it creates new ones. call drop func first*/
/* calling ARCHIVE_ALL_TABLES */
BEGIN
-- Call the function
NULL;
END;
RETURN;
END PKG_TEST_TABLES;
Your LOG_PROC is an autonomous transaction, so you need a COMMIT in there.
You define a number of exceptions, but you don't RAISE them anywhere in your code. For example, I'm guessing you need something like this:
PROCEDURE CREATE_ARCHIVE_TABLES AS
L_NO_TABLES_TO_CREATE EXCEPTION;
l_count number := 0;
BEGIN
FOR STMT IN (SELECT ...)
LOOP
l_count := l_count + 1;
EXECUTE IMMEDIATE STMT.STR;
END LOOP;
IF l_count = 0 THEN
RAISE L_NO_TABLES_TO_CREATE;
END IF;
EXCEPTION
WHEN L_NO_TABLES_TO_CREATE THEN
NULL; --logging can go here
END;

PostgreSQL: Syntax Error when trying to access field in array

I am working on a migration from Oracle 9i to PostgreSQL 9.3 and I need to migrate some packages with their content.
I am using Ora2PG for most of the work, but packages need to be migrated manually considering how specific to Oracle the code is.
I have a user defined Type called RelevCaspTyp with the following definition :
CREATE TYPE pkgstesa5152com.relevcasptyp AS (
-- SOME OTHER DATA
d1 timestamp,
d2 timestamp,
d1min timestamp,
d2min timestamp,
d1max timestamp,
d2max timestamp,
-- SOME OTHER DATA
);
Then, I create an array of objects of this type, in another Type :
CREATE TYPE pkgstesa5152com.relevcasptabtyp AS (relevcasptabtyp pkgstesa5152com.relevcasptyp[]);
And finally here's the function that triggers a syntax error :
CREATE OR REPLACE FUNCTION PkgStesa5152Com.calculd1d2 (RelevCaspTab INOUT pkgstesa5152com.RelevCaspTabTyp, i integer) AS $body$
BEGIN
IF RelevCaspTab[i].d1max IS NULL OR RelevCaspTab[i].d1min >= RelevCaspTab[i].d1max THEN
RelevCaspTab[i].d1 := RelevCaspTab[i].d1min;
ELSE
RelevCaspTab[i].d1 := RelevCaspTab[i].d1max;
END IF;
IF RelevCaspTab[i].d2max IS NULL OR RelevCaspTab[i].d2min >= RelevCaspTab[i].d2max THEN
RelevCaspTab[i].d2 := RelevCaspTab[i].d2min;
ELSE
RelevCaspTab[i].d2 := RelevCaspTab[i].d2max;
END IF;
END;
$body$
LANGUAGE PLPGSQL
;
When I try to import this function in my PostgreSQL database, I get this message :
ERROR: syntax error at or near "."
LINE 5: RelevCaspTab[i].d1 := RelevCaspTab[i].d1min;
^
As odd as it looks, it seems that LINE 4 (with the IF/THEN) passes correctly, unless this is yet another false positive and the issue is actually elsewhere.
EDIT : it looks like the problem actually comes from the affectation of a value to RelevCaspTab[i].d1. If I comment all the affectations in the function, it is created successfully.
if r[i].d1max is null or r[i].d1min >= r[i].d1max then
r[i] := (r[i].d1min,r[i].d2,r[i].d1min,r[i].d2min,r[i].d1max,r[i].d2max);
Edit
As suggested in the comments:
create type relevCaspTyp as (
d1 timestamp,
d1min timestamp,
d1max timestamp
);
create or replace function calculd1d2 (
r inout relevCaspTyp[], i integer
) as $body$
declare a relevCaspTyp;
begin
a := r[i];
if a.d1max is null or a.d1min >= a.d1max then
a.d1 := a.d1min;
else
a.d1 := a.d1max;
end if;
r[i] := a;
end;
$body$
language plpgsql
;
with r (r) as (values (array[('2017-01-01','2017-01-04','2017-01-03')::relevCaspTyp]))
select calculd1d2(r,1)
from r;
calculd1d2
-------------------------------------------------------------------------------
{"(\"2017-01-04 00:00:00\",\"2017-01-04 00:00:00\",\"2017-01-03 00:00:00\")"}

Package Conversion - Oracle to PostgreSQL migration

I am new to Postgres. We are migrating an Oracle db to Postgres. In Oracle we have used so many packages. As per my understanding, there is no Oracle package like functionality in Postgres. I was just trying to find some way to
migrate Oracle packages to Postgres. And in Oracle package, global variables are there.
Please let me know your comments on this - (this is for creating a package named NP_AC015_FETCH).
create or replace package NP_AC015_FETCH is
function FUNC_GET_DATA(P_OUT_CUR out SYS_REFCURSOR) return varchar2;
function FUNC_GET_DATA_AUTO(P_OUT_CUR out SYS_REFCURSOR) return varchar2;
--Added 2006/12/07 - start
PV_LOG_START_MODE constant pls_integer := 0;
PV_LOG_RUNNING_MODE constant pls_integer := 1;
PV_LOG_CLOSE_MODE constant pls_integer := 2;
PV_LOG_ERR_CODE constant pls_integer := -20001;
procedure PROC_LOG(P_MSG in VARCHAR2, P_MODE in pls_integer default PV_LOG_RUNNING_MODE);
end NP_AC015_FETCH;
/
create or replace package body NP_AC015_FETCH is
--Log file
GM_LOG_FILE UTL_FILE.FILE_TYPE;
--String and SQL Keyword
GM_Q constant CHAR := '''';
GM_L constant CHAR := CHR(10);
GM_T constant CHAR := CHR(9);
--alias name
GM_A_HKNSMK constant CHAR(8) := '保険種目';
GM_A_HKNSYR constant CHAR(8) := '保険種類';
GM_A_DISP constant CHAR(6) := '表示置';
GM_A_CNT constant CHAR(6) := '契約数';
GM_A_HKNKGK constant CHAR(8) := '保険金額';
GM_ERR_LINE varchar2(4000);
GM_HANDLED boolean := false;
GM_ERRORSTACK varchar2(2000);
GM_CALLSTACK varchar2(2000);
GM_FORMATTED_STACK varchar2(10000);
function FUNC_HEAD_STMT return varchar2;
function FUNC_END_STMT return varchar2;
procedure PROC_SUB_LOG(P_MSG in varchar2);
procedure PROC_SUB_ERR(P_ERR_LINE varchar2, P_ERR_STACK varchar2, P_CALL_STACK varchar2, P_HANDLE boolean);
/**
* Saving Error Information Procedure
* Parameters:
* P_ERR_LINE -> DBMS_UTILITY.format_error_backtrace
* P_ERR_STACK -> DBMS_UTILITY.format_error_stack
* P_CALL_STACK -> DBMS_UTILITY.FORMAT_CALL_STACK
* P_HANDLE -> If true, error message will create
*/
procedure PROC_SUB_ERR(P_ERR_LINE varchar2,
P_ERR_STACK varchar2,
P_CALL_STACK varchar2,
P_HANDLE boolean) is
begin
/*Save the first call_stack, error_stack at the first instant, ignore the further tracing*/
if not GM_HANDLED then
GM_ERR_LINE := P_ERR_LINE;
GM_HANDLED := true;
GM_ERRORSTACK := P_ERR_STACK;
GM_CALLSTACK := P_CALL_STACK;
end if;
/*THIS BLOCK IS EXECUTED AT BOTTOM MOST PROCEDURE IN THE STACK HIERARCHY*/
if P_HANDLE then
GM_FORMATTED_STACK := CHR(10) ||'==============================================================' ||
CHR(10) || 'Error Stack:' ||
CHR(10) || GM_ERR_LINE ||
CHR(10) || GM_ERRORSTACK ||
CHR(10) || 'CALL Stack:' ||
CHR(10) || gm_CALLSTACK ||
CHR(10) ||
'==============================================================';
end if;
end PROC_SUB_ERR;
/**
* Procedure for output Log messages to a file (External Interface)
* Parameters:
* P_MSG → Output message
* P_MODE → Mode:Start=0,Processing=1, End=2
*/
procedure PROC_LOG(P_MSG in VARCHAR2, P_MODE in pls_integer default PV_LOG_RUNNING_MODE) as
V_F_IS_OPEN boolean; --IF LOG FILE IS ALREADY OPEN THIS IS SET TO TRUE
V_LOG_MSG varchar2(32767); --LOG FILE NAME
V_LOG_DIR varchar2(30) default 'ND_GANJIS_LOG_DIR'; --LOG DIRECOTY
begin
V_F_IS_OPEN := utl_file.is_open(GM_LOG_FILE);
if not V_F_IS_OPEN then
--Log File Open
-- 32767 IS THE MAXIMUM NUMBER OF CHARACTERS PER LINE, INCLUDING THE NEWLINE CHARACTER, FOR THIS FILE.
GM_LOG_FILE := UTL_FILE.FOPEN(V_LOG_DIR, 'NIA_PLSQL_'||to_char(sysdate, 'yyyymmdd')||'.log', 'A', 32767);
end if;
--LOG MSG TO BE WRITTEN TO THE LOG FILE
V_LOG_MSG := TO_CHAR(systimestamp, 'yyyy/mm/dd hh24:mi:ss:ff3') ||' '|| P_MSG;
--Output messages to a file
UTL_FILE.PUT_LINE(GM_LOG_FILE, V_LOG_MSG);
--Closing log file.
if P_MODE = PV_LOG_CLOSE_MODE and utl_file.is_open(GM_LOG_FILE) then
utl_file.fclose(GM_LOG_FILE);
end if;
--HERE THE EXCEPTION PART IS NOT INCLUDED,
--理由: PROGRAM WILL GO ON INFINITE LOOP IF SOME ERROR OCCURS HERE, BECAUSE, EACH EXCEPTION WRITES INTO
--LOG FILE, USING THIS PROCEDURE.
exception
when others then
raise_application_error(PV_LOG_ERR_CODE, dbms_utility.format_error_backtrace||chr(10)||dbms_utility.format_error_stack||chr(10)||dbms_utility.format_call_stack, true);
end PROC_LOG;
/**
* JAVA Interface
*/
function FUNC_GET_DATA(P_OUT_CUR out SYS_REFCURSOR)
return varchar2 as
V_START_TIME pls_integer;
V_RET varchar2(32656);
begin
V_START_TIME := dbms_utility.get_time();
PROC_LOG('NP_AC015_FETCH.FUNC_GET_DATA Process Start', PV_LOG_START_MODE);
V_RET := FUNC_HEAD_STMT
||FUNC_FIRE_STMT
||GM_L ||' union '
||FUNC_GENERAL_STMT
||GM_L ||' union '
||FUNC_ACCIDENT_STMT
||GM_L ||' union '
||FUNC_LI_STMT
||FUNC_END_STMT;
PROC_LOG('SQL query:' ||GM_L|| V_RET);
PROC_LOG('sql文作成終了: '||(dbms_utility.get_time()-V_START_TIME)/100||' sec 桁数:'||LENGTHB(V_RET), PV_LOG_CLOSE_MODE);
PROC_LOG('NP_AC015_FETCH.FUNC_GET_DATA Cursor Open Start Digits:'||LENGTHB(V_RET), PV_LOG_START_MODE);
/*open P_OUT_CUR FOR
select 'FROM NIA PACKAGE'
from DUAL;
*/
open P_OUT_CUR FOR V_RET;
PROC_LOG('Process end'||(dbms_utility.get_time()-V_START_TIME)/100||' sec ', PV_LOG_CLOSE_MODE);
return V_RET;
end FUNC_GET_DATA;
/**
* JAVA Interface FOR AUTO and CALI
*/
function FUNC_GET_DATA_AUTO(P_OUT_CUR out SYS_REFCURSOR)
return varchar2 as
V_START_TIME pls_integer;
V_RET varchar2(32656);
begin
V_START_TIME := dbms_utility.get_time();
PROC_LOG('NP_AC015_FETCH.FUNC_GET_DATA_AUTO Process Start', PV_LOG_START_MODE);
V_RET := FUNC_HEAD_STMT
||FUNC_AUTO_STMT
||GM_L ||' union '
||FUNC_CALI_STMT
||FUNC_END_STMT;
PROC_LOG('SQL query:' ||GM_L|| V_RET);
PROC_LOG('sql statement creation end: '||(dbms_utility.get_time()-V_START_TIME)/100||' sec 桁数:'||LENGTHB(V_RET), PV_LOG_CLOSE_MODE);
PROC_LOG('NP_AC015_FETCH.FUNC_GET_DATA_AUTO Cursor Open Start Digits:'||LENGTHB(V_RET), PV_LOG_START_MODE);
/*open P_OUT_CUR FOR
select 'FROM NIA PACKAGE'
from DUAL;
*/
open P_OUT_CUR FOR V_RET;
PROC_LOG('Process end'||(dbms_utility.get_time()-V_START_TIME)/100||' sec ', PV_LOG_CLOSE_MODE);
return V_RET;
end FUNC_GET_DATA_AUTO;
end NP_AC015_FETCH;
/
You are looking for "stored procedures". Postgres indeed also had that concept and offers several alternative languages.
It is utterly impossible to"convert" the original Oracle packages. You will need to reimplement the code. This would also be a good point in time to think about moving that logic into the application.
There is no package functionality, however, often I use a separate schema to hold my groups of functions to keep them logically together.
Also, as far as variables are concerned, they don't work the same way either. You can use session type variables to achieve a similar result, you can also write a specific function that returns an object (array or hstore) that contains the values, especially if they were just "package level hard coded constants".
create or replace function mypkg.set_global(name varchar) returns varchar as $$
declare
retval varchar;
begin
begin
select current_setting('MYPKG.'||name) into retval;
exception when others then return null;
end;
return retval;
end;
$$ language plpgsql stable;
create or replace function mypkg.get_global(name varchar, val varchar) returns varchar as $$
declare
retval varchar;
begin
begin
select set_config('MYPKG'||name, var, false
exception when others then return null;
end;
return retval;
end;
$$ language plpgsql stable;
Now this provides a method to set and get variables, but they are per session so you need a method to initialize the variables at the beginning. This is useful when wanting to get the current app user, permissions, etc-- the init function can be ran when the person logs in to the app or something.. you'll have to decide what's best here.

How to execute unix command through odi and store the result in table

I have to reconcile the if data is loaded in table from flat file or not . I have to create a oracle data integrator package/interface/procedure to execute unix command to count number of rows in the csv files and store the result in a table then i have to query the loaded table and counfd number of rows there and store in the table and have to compare is counts are same or not, Please assist me how to make package/interface/procedure to execute unix command and store result in oracle table.
Thanks in Advance
I would not solve this using Oracle Data Integrator, but simply use a Oracle package. It is possible to do so when the file which has been processed is on the same node and you can access it using utl_file and similar packages. You can open the CSV from PL/SQL, count the rows taking into the different line end styles available (CR/LF/CRLF) and then close the file again.
This does not give you the other features of running UNIX statements such as 'grep', but with utl_file you can open/read/write/close files and even with some effort list the files in a directory.
A free bonus is that the code becomes more portable to other platforms (Windows, where did VMS go?).
See below some samples taken from software we've developed at Invantive (feel free to use). You might want to use load_xxx_from_directory and then do a regexp_count as a simple solution. Or just count the CR/LF/CRLF yourself in a loop.
--
-- Load a file into a blob. Clob needed? Change blob to clob.
--
procedure load_blob_from_directory
( p_file out nocopy blob
, p_directory all_directories.directory_name%type
, p_filename varchar2
)
is
l_read_buffer_size constant pls_integer := 32767;
--
l_fh utl_file.file_type;
l_read_buffer raw(32767);
l_bytes_read_sofar integer;
l_bytes_read integer;
begin
if p_file is null
then
dbms_lob.createtemporary(p_file, true);
end if;
l_fh := utl_file.fopen(p_directory, p_filename, 'rb');
l_bytes_read_sofar := 0;
begin
while true
loop
utl_file.get_raw(l_fh, l_read_buffer, l_read_buffer_size);
l_bytes_read := length(l_read_buffer) / 2;
dbms_lob.write(p_file, l_bytes_read, l_bytes_read_sofar+1, l_read_buffer);
l_bytes_read_sofar := l_bytes_read_sofar + l_bytes_read;
end loop;
exception
when no_data_found
then
null;
end;
utl_file.fclose(l_fh);
exception
when others
then
--
-- Close file if necessary.
-- Ignore any errors.
--
begin
if utl_file.is_open(l_fh)
then
utl_file.fclose(l_fh);
end if;
exception
when others
then
null;
end;
--
rollback;
itgen_error_handler.add_to_inner_stack;
raise;
end;
Saving to a file:
--
-- Save the file in blob format to an Oracle directory.
--
procedure save_blob_to_directory
( p_file blob
, p_directory all_directories.directory_name%type
, p_filename varchar2
)
is
l_piece_length constant pls_integer := 32767;
--
l_fh utl_file.file_type;
begin
l_fh := utl_file.fopen(p_directory, p_filename, 'wb');
for i in 0 .. trunc((dbms_lob.getlength( p_file ) - 1) / l_piece_length)
loop
utl_file.put_raw
( l_fh
, dbms_lob.substr
( p_file
, l_piece_length
, i * l_piece_length + 1
)
);
end loop;
utl_file.fclose(l_fh);
exception
when others
then
--
-- Close file if necessary.
-- Ignore any errors.
--
begin
if utl_file.is_open(l_fh)
then
utl_file.fclose(l_fh);
end if;
exception
when others
then
null;
end;
--
rollback;
itgen_error_handler.add_to_inner_stack;
raise;
end;
Here is how to get size of a file:
function get_file_length
( p_directory_name varchar2
, p_file_name varchar2
)
return number
is
l_file_length number;
l_file_exists boolean;
l_file_block_size number;
begin
utl_file.fgetattr
( location => p_directory_name
, filename => p_file_name
, fexists => l_file_exists
, file_length => l_file_length
, block_size => l_file_block_size
);
return l_file_length;
end;
Here is how to get contents of a directory:
function list_files
( p_directory_name all_directories.directory_name%type
)
return itgen_tab_file
pipelined
as
l_directory_path all_directories.directory_path%type;
l_ns varchar2(1024);
begin
select dry.directory_path
into l_directory_path
from all_directories dry
where dry.directory_name = p_directory_name
;
sys.dbms_backup_restore.searchfiles(l_directory_path, l_ns);
for r_files in
( select fname_krbmsft file_name
from sys.itgen_x_krbmsft
)
loop
pipe row
( itgen_rec_file
( p_directory_name
, r_files.file_name
, itgen_utilities.get_file_length (p_directory_name, r_files.file_name)
)
);
end loop;
end;

Porting Oracle Procedure (With Specific Function Calls) To Postgres PL/PGSQL

(This is similar to a question I asked earlier: Porting Oracle Procedure to PostgreSQL)
I need to port:
/*
|| The following private procedure will execute a dynamic pl/sql
|| statement passed to it.
*/
CREATE OR REPLACE FUNCTION DB_SHELL_UTIL_PKG.EXECUTE_STMT (stmt VARCHAR) IS
v_num_rows integer;
v_cursor_table integer;
BEGIN
v_cursor_table := dbms_sql.open_cursor;
dbms_sql.parse (v_cursor_table, stmt, dbms_sql.v7);
v_num_rows := dbms_sql.execute (v_cursor_table);
dbms_sql.close_cursor(v_cursor_table);
END execute_stmt;
and
/*
|| The following private procedure will write out to a system
|| file the statement passed to it.
*/
CREATE OR REPLACE FUNCTION DB_SHELL_UTIL_PKG.write_log_info (p_path IN VARCHAR2,
p_file_name IN VARCHAR2,
stmt IN VARCHAR2 ) IS
log_file UTL_FILE.FILE_TYPE;
BEGIN
log_file := UTL_FILE.FOPEN (p_path, p_file_name, 'A');
UTL_FILE.PUT_LINE (log_file,stmt);
UTL_FILE.FCLOSE(log_file);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(log_file);
RAISE;
END write_log_info;
and
/*
|| The following procedure will drop the user passed to it
|| and then record its action by writing out to a system file
*/
PROCEDURE DROP_DB_PRO ( p_db_name IN VARCHAR2,
p_path IN VARCHAR2,
p_file_name IN VARCHAR2,
p_status OUT VARCHAR2 ) IS
v_stmt VARCHAR2(1500);
BEGIN
v_stmt := 'DROP USER '||p_db_name||' CASCADE';
execute_stmt (v_stmt);
p_status := 'USER '||p_db_name|| ' HAS BEEN DROPPED';
v_stmt := 'THE USER '||p_db_name||' HAS BEEN DROPPED';
write_log_info(p_path, p_file_name, v_stmt);
EXCEPTION
WHEN OTHERS THEN
v_stmt := 'EXCEPTION raised in DROP_DB_PRO';
write_log_info (p_path, p_file_name, v_stmt);
RAISE;
END DROP_DB_PRO;
From Oracle to PG/PLSQL...
I have gotten this far:
CREATE OR REPLACE FUNCTION DB_SHELL_UTIL_PKG.EXECUTE_STMT (stmt VARCHAR)
RETURNS void as '
DECLARE
v_num_rows integer;
v_cursor_table integer;
BEGIN
v_cursor_table := dbms_sql.open_cursor;
dbms_sql.parse (v_cursor_table, stmt, dbms_sql.v7);
v_num_rows := dbms_sql.execute (v_cursor_table);
dbms_sql.close_cursor(v_cursor_table);
END execute_stmt;
' LANGUAGE plpgsql;
Which chokes on:
ERROR: syntax error at or near "dbms_sql"
LINE 1: dbms_sql.parse ( $1 , $2 , dbms_sql.v7)
and
CREATE OR REPLACE FUNCTION DB_SHELL_UTIL_PKG.write_log_info (p_path VARCHAR,
p_file_name VARCHAR,
stmt VARCHAR )
RETURNS void as '
log_file UTL_FILE.FILE_TYPE;
BEGIN
log_file := UTL_FILE.FOPEN (p_path, p_file_name, ''A'');
UTL_FILE.PUT_LINE (log_file,stmt);
UTL_FILE.FCLOSE(log_file);
EXCEPTION
WHEN OTHERS THEN
UTL_FILE.FCLOSE(log_file);
RAISE;
END write_log_info;
' LANGUAGE plpgsql;
which chokes on:
ERROR: syntax error at or near "log_file"
LINE 6: log_file UTL_FILE.FILE_TYPE
and
CREATE OR REPLACE FUNCTION DB_SHELL_UTIL_PKG.DROP_DB_PRO ( p_db_name VARCHAR,
p_path VARCHAR,
p_file_name VARCHAR,
p_status VARCHAR )
RETURNS varchar as '
DECLARE
v_stmt VARCHAR(1500);
BEGIN
v_stmt := 'DROP USER '||p_db_name||' CASCADE';
execute_stmt (v_stmt);
p_status := 'USER '||p_db_name|| ' HAS BEEN DROPPED';
v_stmt := 'THE USER '||p_db_name||' HAS BEEN DROPPED';
write_log_info(p_path, p_file_name, v_stmt);
return(p_status);
EXCEPTION
WHEN OTHERS THEN
v_stmt := 'EXCEPTION raised in DROP_DB_PRO';
write_log_info (p_path, p_file_name, v_stmt);
RAISE;
END DROP_DB_PRO;
' LANGUAGE plpgsql;
Help with any of these would be much appreciated (I am new to the world of functions/stored procedures)
For the DBMS_SQL one, look at Dynamic SQL in plpgsql
For UTL_FILE, you'll have to look beyond plpgsql or at Orafce
Orafce can UTL_FILE, just need to update documentation

Resources