associate array constructor not found when compiling a stored procedure - oracle

When using a type that is already defined in a package as
Type ArrError Is Table Of Varchar2(20) Index By Binary_Integer;
and declaring it as following in a stored procedure
arr_error(1) := PKG_TEST.arrerror(p_error);
results in the following error PLS-00222: no function with name 'ARRERROR' exists in this scope. In the above statement p_error is of type VARCHAR2
When using a global type created using CREATE TYPE command this works fine.
using the above initialization in a CREATE PROCEDURE block.

You don't need to initialize if you got Index by ...
declare
TYPE ArrError IS TABLE OF VARCHAR2 (20) index by binary_integer;
arr_error ArrError;
p_error varchar2(20) := 'test';
p_error2 varchar2(20) := 'test2';
begin
arr_error(1) := p_error;
arr_error(2) := p_error2;
dbms_output.put_line('arr_error(1): ' || arr_error(1));
dbms_output.put_line('arr_error(2): ' || arr_error(2));
end;
If you don't have index by ... you need to call the constructor:
declare
TYPE ArrError IS TABLE OF VARCHAR2 (20);
arr_error ArrError;
p_error varchar2(20) := 'test';
p_error2 varchar2(20) := 'test2';
begin
-- Needed because of no 'Indexed by'. Or else you get a 'ORA-06531' not initialized..
arr_error := ArrError(p_error);
arr_error.extend;
arr_error(2) := p_error2;
dbms_output.put_line('arr_error(1): ' || arr_error(1));
dbms_output.put_line('arr_error(2): ' || arr_error(2));
end;

Related

PLSQL variable doesn't get assigned by the given value

I am trying to assign a value from a table type variable to a varchar2 type table
CREATE OR REPLACE PACKAGE BODY TEST_SYS IS
TYPE line_table IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
PROCEDURE test(
val_ OUT VARCHAR2)
IS
temp_val VARCHAR2(4000);
svalues_ line_Table;
BEGIN
svalues_(1) := '! -$FILE_LINE=EXT01;2017-01;2017-
12;JJ01;;4021;;;;;;;;;;;;USD;;;;;;;;1000;1000;; -';
temp_val := svalues_(1);
val_ := temp_val;
END test;
END TEST_SYS
value assignment seems does not happen in the following statement. Does anybody has a clue on this?
temp_val := svalues_(1);
This example only for problem replicate, It may be not logically enhanced one. only to understand the problem.
Provided you have a package test_sys with code :
CREATE OR REPLACE PACKAGE TEST_SYS IS
PROCEDURE test( val_ OUT VARCHAR2);
END TEST_SYS;
and body of the package :
CREATE OR REPLACE PACKAGE BODY TEST_SYS IS
TYPE line_table IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
PROCEDURE test( val_ OUT VARCHAR2) IS
temp_val varchar2(4000);
svalues_ line_Table;
BEGIN
svalues_(1) := '! -$FILE_LINE=EXT01;2017-01;2017-12;JJ01;;4021;;;;;;;;;;;;USD;;;;;;;;1000;1000;; -';
temp_val := svalues_(1);
val_ := temp_val;
dbms_output.put_line(val_);
END test;
END TEST_SYS;
and call procedure test, you will be able to get the results as in the following :
SQL> set serveroutput on;
SQL> var str varchar2(4000);
SQL> exec test_sys.test(:str);
PL/SQL procedure successfully completed
str
---------
! -$FILE_LINE=EXT01;2017-01;2017-12;JJ01;;4021;;;;;;;;;;;;USD;;;;;;;;1000;1000;; -

Plsql - Evaluate a dynamic string

I need to build a process that creates tables dynamically.
I have this:
declare
type array is table of varchar2(30) index by binary_integer;
a array;
expression varchar2(2000);
RESUME_create LONG;
procedure createTables ( texto in VARCHAR2 ) is
begin
dbms_output.put_line('the parameter is: ' || texto);
expression := 'begin ' || texto || '; end;';
dbms_output.put_line(expression);
execute immediate expression;
end;
RESUME_create := 'CREATE TABLE RESUME (
R_Resume_date DATE DEFAULT SYSDATE NOT NULL ,
R_Resume_source CHAR(3) DEFAULT ''001'' NOT NULL ,
R_Resume_channel CHAR(3) DEFAULT ''001'' NOT NULL )';
createTables('RESUME_create');
end;
/
So this is just an example.
So imagine that I need to declare multiples CREATE TABLEs and call the createTable into a loop passing multiples string that the function has to evaluate and execute.
If I un understand well, you need to run a set of DDL statements stored in a collection. If so, you can use something like:
declare
type tArray is table of varchar2(1000) index by pls_integer;
vArray tArray ;
begin
vArray(1) := 'create table firstTab ( a number, b number)';
vArray(2) := 'create table secondTab ( c number, d varchar2(10))';
--
for i in vArray.first .. vArray.last loop
execute immediate vArray(i);
end loop;
end;
/

how to pass object type as a parameter in oracle

below abstarct type created
create or replace TYPE callbck as table of callback_t;
abstract table
create or replace TYPE CALLBACK_T as object
(
url varchar2(50),
uri_key number,
);
below is the procedure used,
procedure get_callback_info
(
pi_clbk callbck := callbck (),
requestor varchar2,
msg varchar2)
how to pass the parameter for the abstract object type to the procedure get_callback_info.
i have the abstract values 'http://test.com', and 1345 as the url and uri_key
Say you have these types and procedure:
CREATE OR REPLACE TYPE CALLBACK_T AS OBJECT
(
url VARCHAR2(50),
uri_key NUMBER
);
CREATE OR REPLACE TYPE callbck AS TABLE OF callback_t;
CREATE OR REPLACE PROCEDURE get_callback_info(
pi_clbk IN callbck := callbck(),
requestor IN VARCHAR2,
msg OUT VARCHAR2
) IS
BEGIN
/* whatever your code is */
msg := requestor || ' asked information on callbck with ' || pi_clbk.COUNT || ' elements';
END;
You can test your procedure with something like:
declare
vCallbck callbck;
vRequestor varchar2(20) := 'a requestor';
vMsg varchar2(100);
begin
/* populate the vCallbck with 10 records */
select CALLBACK_T ('url ' || level, level)
bulk collect into vCallbck
from dual
connect by level <= 10;
--
get_callback_info(vCallbck, vRequestor, vMsg);
--
dbms_output.put_line(vMsg);
end;
/
If you want to test with a single value, you can use:
declare
vCallbck callbck;
vRequestor varchar2(20);
vMsg varchar2(100);
begin
vCallbck := callbck();
vCallbck.extend(1);
vCallbck(1) := CALLBACK_T('http://test.com', '1345');
--
get_callback_info(vCallbck, vRequestor, vMsg);
--
dbms_output.put_line(vMsg);
end;
/

pass function argument to cursor in oracle

I am getting an error while passing function argument to the cursor. Here is the Below example
Create OR Replace FUNCTION UPD_TAB(ID_VAL IN OUT VARCHAR2,SRC_COLUMN IN OUT VARCHAR2,DEST_COLUMN IN OUT VARCHAR2,OWNER_TAB IN OUT VARCHAR2,SRC_TAB IN OUT VARCHAR2,DEST_TAB IN OUT VARCHAR2)
RETURN VARCHAR2
IS
SRC_COL VARCHAR2(30) := SRC_COLUMN;
DEST_COL VARCHAR2(20) := DEST_COLUMN;
ID_VALUE VARCHAR2(20) := ID_VAL;
SRC_TABLE VARCHAR(20) := SRC_TAB;
DEST_TABLE VARCHAR(20) := DEST_TAB;
TAB1 VARCHAR2(40) := OWNER_TAB||'.'||SRC_TAB;
TAB2 VARCHAR2(40) := OWNER_TAB||'.'||DEST_TAB;
CURSOR RET_VAL
IS
SELECT C1.SRC_COL,C2.DEST_COL
FROM TAB1 C1,TAB2 C2
WHERE C1.SRC_COL=C2.DEST_COL
AND C1.ID=ID_VALUE;
Here in the above example when pass pass the actual database values Schemaname.Tablename
eg. grany.Booking . It output the results but when i pass the variable having value TAB1 and TAB2. It shows the following error
PL/SQL: ORA-00942: table or view does not exist
22/11 PL/SQL: Statement ignored
i searched a lot but didn't find the solution
I know what error is trying to say but i dont know how to fix the solution for this one.
Any help will be appreciated. Thanks in advance.
Static cursors cannot obtain table and column names from variables. One way to get around this is to build the query in a VARCHAR2 variable and then open a generic cursor (SYS_REFCURSOR type, defined in package SYS.STANDARD) for the query string:
CREATE OR REPLACE FUNCTION UPD_TAB(ID_VAL IN OUT VARCHAR2,
SRC_COLUMN IN OUT VARCHAR2,
DEST_COLUMN IN OUT VARCHAR2,
OWNER_TAB IN OUT VARCHAR2,
SRC_TAB IN OUT VARCHAR2,
DEST_TAB IN OUT VARCHAR2)
RETURN VARCHAR2
IS
SRC_COL VARCHAR2(30) := SRC_COLUMN;
DEST_COL VARCHAR2(20) := DEST_COLUMN;
ID_VALUE VARCHAR2(20) := ID_VAL;
SRC_TABLE VARCHAR2(20) := SRC_TAB;
DEST_TABLE VARCHAR2(20) := DEST_TAB;
TAB1 VARCHAR2(40) := OWNER_TAB||'.'||SRC_TAB;
TAB2 VARCHAR2(40) := OWNER_TAB||'.'||DEST_TAB;
vVAL1 VARCHAR2(2000);
vVAL2 VARCHAR2(2000);
strCursor VARCHAR2(32767) :=
'SELECT C1.' || SRC_COL ||
',C2.' || DEST_COL ||
'FROM ' || TAB1 || ' C1, ' ||
TAB2 || ' C2 ' ||
'WHERE C1.' || SRC_COL || '=C2.' || DEST_COL || ' AND ' ||
'C1.ID=' || ID_VALUE;
csr SYS_REFCURSOR;
BEGIN
OPEN csr FOR strCursor;
LOOP
FETCH csr
INTO vVAL1, vVAL2;
EXIT WHEN csr%NOTFOUND;
-- Do something useful with values fetched from cursor;
END LOOP;
CLOSE csr;
END UPD_TAB;
Share and enjoy.

Using Tables of Records in PL/SQL

I've declared the following types in my PL/SQL package:
TYPE t_simple_object IS RECORD (
wert NUMBER,
gs NUMBER,
vl NUMBER);
TYPE t_obj_table IS TABLE OF t_simple_object
INDEX BY BINARY_INTEGER;
Then I declare a variable:
obj t_obj_table;
However, when I want to use the variable, I cannot initialize or extend it:
obj := t_obj_table ();
gives the following errror:
PLS-00222: no function with name 'T_OBJ_TABLE' exists in this scope
If I don't initialize it, I can't extend it to add some date as
obj.EXTEND();
gives another error:
PLS-00306: wrong number or types of arguments in call to 'EXTEND'
How can I make this work?
You don't extend a table indexed by "something", you can just use it...
DECLARE
TYPE t_simple_object IS RECORD
( wert NUMBER
, gs NUMBER
, vl NUMBER
);
TYPE t_obj_table IS TABLE OF t_simple_object
INDEX BY BINARY_INTEGER;
my_rec t_simple_object;
obj t_obj_table;
BEGIN
my_rec.wert := 1;
my_rec.gs := 1;
my_rec.vl := 1;
obj(1) := my_rec;
END;
/
To use the EXTEND syntax, this example should do it...
DECLARE
TYPE t_simple_object IS RECORD
( wert NUMBER
, gs NUMBER
, vl NUMBER
);
TYPE t_obj_table IS TABLE OF t_simple_object;
my_rec t_simple_object;
obj t_obj_table := t_obj_table();
BEGIN
obj.EXTEND;
my_rec.wert := 1;
my_rec.gs := 1;
my_rec.vl := 1;
obj(1) := my_rec;
END;
/
Also see this link (Ask Tom)
If you don't want to use an associative array (aka index-by table) then leave out the "INDEX BY BINARY_INTEGER" clause. Your code then works OK:
declare
TYPE t_simple_object IS RECORD (
wert NUMBER,
gs NUMBER,
vl NUMBER);
TYPE t_obj_table IS TABLE OF t_simple_object;
obj t_obj_table;
begin
obj := t_obj_table ();
obj.EXTEND();
end;
You can not extend an assosiative array.
Just assign values to it
declare
TYPE t_simple_object IS RECORD (
wert NUMBER,
gs NUMBER,
vl NUMBER);
TYPE t_obj_table IS TABLE OF t_simple_object INDEX BY BINARY_INTEGER;
simple_object t_simple_object;
begin
simple_object.wert := 1;
simple_object.gs := 2;
simple_object.vl := 3;
obj(1) := simple_object;
end;
/
Or just use a record ( or associate array of records )
create or replace package p_test is
type t_rec is record (
empname varchar2(50),
empaddr varchar2(50));
function p_test_ret_record return t_rec;
end p_test;
create or replace package body p_test is
function p_test_ret_record return t_rec is
l_rec t_rec;
begin
l_rec.empname := 'P1';
l_rec.empaddr := 'P2';
return l_rec;
end;
end p_test;
declare
-- Non-scalar parameters require additional processing
result p_test.t_rec;
begin
-- Call the function
result := p_test.p_test_ret_record;
dbms_output.put_line('Name: ' || result.empname || ' Addr: ' || result.empaddr);
end;

Resources