I'm getting this error:
Error while executing the procedure : ORA-06530: Reference to uninitialized composite
This is probably a common error for Oracle beginners like me. I looked at similar posts but can't figure out how to apply the answers to my code, which follows.
I have a table of:
CREATE OR REPLACE TYPE "FDS_APPS"."TY_AUDIT_COL_TBL" IS
TABLE OF fds_apps.ty_audit_col_obj;
of this TYPE
CREATE OR REPLACE TYPE "FDS_APPS"."TY_AUDIT_COL_OBJ" AS OBJECT (
application VARCHAR2(30),
module VARCHAR2(30),
created_by VARCHAR2(50),
creation_date DATE
);
I want to create a a test procedure to call the following procedure while passing in the input values with focus, of course on the p_audit_col parameter of type ty_audit_col_tbl.
PROCEDURE check_mv_status (
o_outcome_type OUT VARCHAR2,
p_audit_col IN fds_apps.ty_audit_col_tbl,
p_refresh_ind IN CHAR DEFAULT 'N',
p_mv_result OUT NOCOPY fds_apps.ty_result_tbl
) AS...
Here is my calling procedure:
CREATE OR REPLACE PROCEDURE FDS_APPS.JUNKPROC2
AS
O_OUTCOME_TYPE VARCHAR2(32767);
P_AUDIT_COL TY_AUDIT_COL_TBL;
P_REFRESH_IND CHAR;
P_MV_RESULT TY_RESULT_TBL;
BEGIN
P_AUDIT_COL := fds_apps.TY_AUDIT_COL_TBL();
P_AUDIT_COL.extend(1);
--Error occurs on the following line
P_AUDIT_COL(1).application := 'App';
P_AUDIT_COL(1).module := 'Module';
P_AUDIT_COL(1).created_by := 'MyID';
P_REFRESH_IND := 'N';
FIRM_RTBI_PKG.CHECK_MV_STATUS(O_OUTCOME_TYPE, P_AUDIT_COL, P_REFRESH_IND, P_MV_RESULT);
dbms_output.put_line('O_OUTCOME_TYPE=' || O_OUTCOME_TYPE);
END;
/
I get the error where indicated as a comment, when I try to assign a value to an element in the 1 record collection.
How can I overcome this error?
The syntax you are showing is for populating RECORDS, which is different than populating an OBJECT type.
Replace this:
P_AUDIT_COL(1).application := 'App';
P_AUDIT_COL(1).module := 'Module';
P_AUDIT_COL(1).created_by := 'MyID';
with this:
P_AUDIT_COL(1) := TY_AUDIT_COL_OBJ('App','Module','MyID',sysdate);
An object type variable needs to be initialized with a constructor
Related
Hi I am trying to execute below statements for creating a package , but i am getting an error saying
Error(3,1): PLS-00540: object not supported in this context.
When trying to change it to RECORD i am getting another error
Error(3,32): PLS-00103: Encountered the symbol "RECORD" when expecting one of the following:
object opaque The symbol "object was inserted before "RECORD" to continue.
package Definition trying to execute
CREATE OR REPLACE PACKAGE "PKG_LOAN_LOGIC_SERVICE_V2" AS
TYPE LOAN_LOGIC_RESULT_TYPE AS OBJECT (
loanid NUMBER,
ret_value varchar2(500),
xPath varchar2(200)
);
TYPE LOAN_LOGIC_RESULTS_TABLE IS TABLE OF LOAN_LOGIC_RESULT_TYPE;
procedure PR_CORAL_LOAN_LOGIC(
in_loan_id IN wcts.loans.loan_id%TYPE,
in_trans_id IN wcts.loans.loan_id%TYPE,
as_errm out varchar2,
out_order_contents_tab out LOAN_LOGIC_RESULTS_TABLE
);
END PKG_LOAN_LOGIC_SERVICE_V2;
When i am trying to execute the user defined types in another standalone SQL Developer Window , its executing successfully .
CREATE OR REPLACE TYPE LOAN_LOGIC_RESULT_TYPE AS OBJECT (
loanid NUMBER,
ret_value varchar2(500),
xPath varchar2(200)
);
CREATE OR REPLACE TYPE LOAN_LOGIC_RESULTS_TABLE AS TABLE OF LOAN_LOGIC_RESULT_TYPE;
Why its not allowing me to run inside package ? or how i will create these types inside a package
Update:
create or replace procedure PR_CORAL_LOAN_LOGIC(
in_loan_id IN wcts.loans.loan_id%TYPE,
in_trans_id IN wcts.loans.loan_id%TYPE,
as_errm out varchar2,
out_order_contents_tab out LOAN_LOGIC_RESULTS_TABLE
)
is
begin
for o in (SELECT xpath_name FROM loan_logic WHERE attribute =
upper(TRIM('STATUS_0')))
loop
-- How i will get the user defined type here tp assign the values
--Assign the column values while iterating
END LOOP;
end PR_CORAL_LOAN_LOGIC;
According to Oracle documentation
You must define object types using the SQL statement CREATE TYPE
EDIT
For example
create or replace procedure PR_CORAL_LOAN_LOGIC(out_order_contents_tab out LOAN_LOGIC_RESULTS_TABLE)
is
obj LOAN_LOGIC_RESULT_TYPE;
begin
obj := LOAN_LOGIC_RESULT_TYPE(2, 'return value', 'some/path');
out_order_contents_tab := LOAN_LOGIC_RESULTS_TABLE();
out_order_contents_tab.extend;
out_order_contents_tab(1) := obj;
There are lots of examples available online, including Working with Collections. Not to mention the Oracle documentation.
I have several user-defined types in PL/SQL packet:
TYPE blk_esta IS RECORD (
codi_mone VARCHAR2(1),
codi_situ VARCHAR2(1),
situ_pig VARCHAR2(1),
IMPORTE NUMBER(11,2)
);
TYPE oper_data_mv_out IS RECORD
(
bloq_esta blk_esta,
bloq_aseg blk_aseg
);
I have a BBDD with the names and fields order. So I obtain then name of the first field and I want to assign dynamically a value.
select name into field from GFM_MODEL;
I have tried several things:
sql:= 'SELECT ''E'' into oper_data.bloq_esta.'||name||' from dual';
execute immediate (sql);
out: ORA-00905: missing keyword
sql :='oper_data.bloq_esta.:b1:=''E''';
execute immediate (slq) using in out oper_data;
out:PLS-00457: expressions have to be of SQL types
Any idea how I could do this?
Thanks in advance.
Edit: I need it because my struct is much bigger than the example, I want to define the model of the struct in a table with code_bloq, name_bloq, etc. And when someone needs to add a new field, only have to insert in the table. And the program reads in the table the new field and no need to modify the code. Look the struct:
TYPE oper_data_mv_out IS RECORD
(
bloq_esta blk_esta,
bloq_aseg blk_aseg,
bloq_toma blk_toma,
lista_bene tabla_bene,
bloq_plan blk_plan,
lista_inte tabla_inte,
bloq_tari blk_tari,
bloq_hist blk_hist,
bloq_resc blk_resc,
bloq_repr blk_repr,
bloq_fide blk_fide,
bloq_comu blk_comu,
lista_cuen tabla_cuen,
bloq_cumu blk_cumu,
bloq_part blk_part,
bloq_esp2 blk_esp2,
bloq_esp3 blk_esp3,
bloq_esp4 blk_esp4,
bloq_esp5 blk_esp5,
bloq_esp6 blk_esp6,
bloq_esp7 blk_esp7,
bloq_esp8 blk_esp8,
bloq_esp9 blk_esp9,
bloq_esp10 blk_esp10,
bloq_esp11 blk_esp11,
bloq_esp12 blk_esp12,
lista_blk_camp tabla_blk_camp,
lista_blk_warn tabla_blk_warn
);
Other solution could be assign the data with other references... instead of oper_data_mv_out.bloq_esta.(1). Any idea?
First, redeclare your packaged (PL/SQL record) types to schema-level (SQL object) types.
Then your code
sql :='oper_data.bloq_esta.:b1:=''E''';
execute immediate (slq) using in out oper_data;
should work... with a slight modification, of course...
sql :='
declare
l_oper_data oper_data_mv_out := :oper_data;
begin
l_oper_data.bloq_esta.'||field_name||' := ''E'';
:oper_data := l_oper_data;
end;
';
execute immediate sql
using in out oper_data;
A proof of concept
First, the schema-level type...
create or replace type obj_so_variable_field_name
as
object (
field_1 varchar2(32),
field_2 varchar2(32),
field_of_corn varchar2(32),
field_of_maze varchar2(32),
fieldy_of_korn varchar2(32)
);
/
Now the dynamic field modification...
declare
l_record obj_so_variable_field_name := new obj_so_variable_field_name(null, null, null, null, null);
l_field_to_change constant varchar2(30) := 'field_of_corn';
l_value_to_change constant varchar2(32) := '42';
begin
dbms_output.put_line('*** before the change');
dbms_output.put_line('>'||l_record.field_1);
dbms_output.put_line('>'||l_record.field_2);
dbms_output.put_line('>'||l_record.field_of_corn);
dbms_output.put_line('>'||l_record.field_of_maze);
dbms_output.put_line('>'||l_record.fieldy_of_korn);
dbms_output.put_line('*** now changing '||l_field_to_change||' to value of "'||l_value_to_change||'"');
execute immediate '
declare
l_oper_data obj_so_variable_field_name := :oper_data;
begin
l_oper_data.'||l_field_to_change||' := :in_value;
:oper_data := l_oper_data;
end;
' using
in out l_record,
in l_value_to_change
;
dbms_output.put_line('*** after the change');
dbms_output.put_line('>'||l_record.field_1);
dbms_output.put_line('>'||l_record.field_2);
dbms_output.put_line('>'||l_record.field_of_corn);
dbms_output.put_line('>'||l_record.field_of_maze);
dbms_output.put_line('>'||l_record.fieldy_of_korn);
end;
/
... which, upon running, yields...
*** before the change
>
>
>
>
>
*** now changing field_of_corn to value of "42"
*** after the change
>
>
>42
>
>
I have the following types defined into a spec of a package
type column_info is record (col_name varchar2(20), col_value varchar2(1000));
type c_info is varray(10) of column_info;
type table_info is record (table_name varchar2(20), col_info c_info);
In declaration part package body I have
t_info table_info;
Inside of a procedure in the body of package I have
t_info:=null;
t_info.table_name:='gl_temp_report1';
t_info.col_info(1).col_name:='table_idx';
t_info.col_info.extend;
t_info.col_info(2).col_name:='table_row';
t_info.col_info.extend;
t_info.col_info(3).col_name:='table_row_detail';
Even package compile succesfully , at runtime I get the exception ORA-06531: Reference to uninitialized collection .
How I initialize col_info collection ?
I tried to initialize t_info.col_info() but I get "There is no function" like this one . TIA, Aurel
You should initialize all collections (including nested) properly before accessing them.
They are atomically nulls before initialization.
t_info := table_info('gl_temp_report1', c_info());
You also must call extend before assigning a value for each varray element (or extend once with extend(3)).
Or do it all in one statement:
t_info := table_info('gl_temp_report1', c_info('table_idx','table_row','table_row_detail'));
To perform initialization you'll need to add an initialization block to the package body, in a manner similar to the following:
CREATE OR REPLACE PACKAGE BODY your_package IS
t_info table_info;
-- Whatever other procedure definitions, etc, are needed
BEGIN -- package initialization
t_info.table_name:='gl_temp_report1';
t_info.col_info := c_info();
t_info.col_info.extend;
t_info.col_info(1).col_name:='table_idx';
t_info.col_info.extend;
t_info.col_info(2).col_name:='table_row';
t_info.col_info.extend;
t_info.col_info(3).col_name:='table_row_detail';
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Exception!'); -- Add whatever error handling is needed
END your_package;
Share and enjoy.
You can create t_info as shown:
declare
type column_info is record (col_name varchar2(20), col_value varchar2(1000));
type c_info is varray(10) of column_info;
type table_info is record (table_name varchar2(20), col_info c_info);
t_info table_info;
begin
t_info.table_name := null;
t_info.col_info := c_info();
for i in 1..10 loop
t_info.col_info.extend;
t_info.col_info(i).col_name := null;
t_info.col_info(i).col_value := null;
end loop;
end;
/
Cheers!
I am trying to print an table type for debugging purposes, but don't know how. I tried the following two methods, neither of which work:
dbms_output.put_line (V_TEMP_TABTYPE(1));
dbms_output.put_line (V_TEMP_TABTYPE);
The error generated is: PLS-00306: wrong number or types of arguments in call to.
So, how can I print the contents of a table type? Or is there a different way to display the contents?
The table_type and the type it references are::
create or replace TYPE MY_TYPE IS OBJECT( MyString Varchar(20)
, counter Number(9) );
create or replace TYPE MY_TABTYPE AS TABLE OF MY_TYPE;
Oracle has objects but it's ... different. Not exactly sure with your question if you want to see the values of the properties or if you want to actually see the type.
CREATE OR REPLACE TYPE MY_TYPE IS OBJECT (
MyString Varchar(20)
, counter Number(9)
);
Now run some code for it.
DECLARE
myType MY_TYPE;
BEGIN
myType := MY_TYPE('ABC123',0);
-- To see the values reference the properties
DBMS_OUTPUT.PUT_LINE(myType.mystring);
-- To see they TYPE of the OBJECT
DBMS_OUTPUT.PUT_LINE(SYS.ANYDATA.CONVERTOBJECT(myType).getTypeName());
END;
Of course you can create methods on the object to return information for you a bit easier.
CREATE OR REPLACE TYPE MY_TYPE IS OBJECT (
MyString Varchar(20)
, counter Number(9)
, MEMBER FUNCTION getType RETURN VARCHAR2
, MEMBER FUNCTION toString RETURN VARCHAR2
)
/
CREATE OR REPLACE TYPE BODY MY_TYPE
AS
MEMBER FUNCTION getTYPE RETURN VARCHAR2 IS
BEGIN
RETURN SYS.ANYDATA.CONVERTOBJECT(SELF).getTypeName();
END;
MEMBER FUNCTION toString RETURN VARCHAR2 IS
BEGIN
RETURN 'MY_TYPE('||self.mystring||','||self.counter||')';
END;
END;
/
You can call the functions on the object now makes it easier to read imo.
DECLARE
mytype MY_TYPE;
BEGIN
mytype := MY_TYPE('AGAIN','0');
DBMS_OUTPUT.PUT_LINE(mytype.toString);
DBMS_OUTPUT.PUT_LINE(mytype.getType);
END;
dbms_output.put_line(v_temp_tabtype(i).myString);
This has been driving me crazy for a while:
DECLARE
TYPE AttrValueRec IS RECORD (
attr VARCHAR2(40),
val VARCHAR2(2000),
inst NUMBER(4)
);
FUNCTION create_attrval(attr AttrValueRec.attr%TYPE,
val AttrValueRec.val%TYPE,
inst AttrValueRec.inst%TYPE := 1)
RETURN AttrValueRec IS
attr_value AttrValueRec;
BEGIN
attr_value.attr := attr;
attr_value.val := val;
attr_value.inst := inst;
RETURN attr_value;
END;
BEGIN
NULL;
END;
Using %TYPE on a record field does not seem to work. It produces the following error:
ORA-06550: line 8, column 36:
PLS-00206: %TYPE must be applied to a variable, column, field or attribute, not to "ATTRVALUEREC.ATTR"
ORA-06550: line 8, column 5:
PL/SQL: Item ignored
While explicitly defining the type again works:
DECLARE
TYPE AttrValueRec IS RECORD (
attr VARCHAR2(40),
val VARCHAR2(2000),
inst NUMBER(4)
);
FUNCTION create_attrval(attr VARCHAR2,
val VARCHAR2,
inst NUMBER := 1)
RETURN AttrValueRec IS
attr_value AttrValueRec;
BEGIN
attr_value.attr := attr;
attr_value.val := val;
attr_value.inst := inst;
RETURN attr_value;
END;
BEGIN
NULL;
END;
Can someone explain to me why it doesn't work? Is there a way to refer to the type declared in the record definition instead of explicitly defining it again in the function?
Thanks.
You need to actually create a variable of your type to refer to the attributes.
Add this after your type declaration and before the function.
attrib_value AttribValueRec;
Then in your function header you can reference the type of the attributes in your function like this:
attr attrib_value.attr%TYPE;
look at documentation. %TYPE and %ROWTYPE - only use to refer database columns. but you try to make referer to user type.
solution is define your pl/sql type with %TYPE-referer on a database column, and then create function with parameters that refer to the same database column.
UPDATE
its not full truth because lead commentator post usefull idea. summary %TYPE and %ROWTYPE can refer not only to table columns. refer ot "real" objects like variables and cursors are good too.