ORA-06531: Reference to uninitialized collection - collections

I am getting "ORA-06531: Reference to uninitialized collection" even after initializing collection to assign a value. Could you please help. Please find the code below.
create or replace TYPE TYP_GRP_ID is object (grp_id number);
create or replace TYPE TAB_GROUP is table of TYP_GRP_ID;
create or replace PACKAGE TEST AS
PROCEDURE TEST;
END;
create or replace PACKAGE BODY TEST AS
PROCEDURE TEST
IS
acc_arr TAB_GROUP;
BEGIN
acc_arr.EXTEND;
acc_arr := new TAB_GROUP(null);
acc_arr(acc_arr.LAST).grp_id := 1000;
dbms_output.put_line(acc_arr(acc_arr.LAST).grp_id);
END;
END;
Thanks in advance.
Mathew

Need to initialize acc_arr, see updated code below
create or replace PACKAGE BODY TEST AS
PROCEDURE TEST
IS
acc_arr TAB_GROUP := TAB_GROUP();
BEGIN
acc_arr.EXTEND;
-- acc_arr := new TAB_GROUP(null);
acc_arr(acc_arr.LAST).grp_id := 1000;
dbms_output.put_line(acc_arr(acc_arr.LAST).grp_id);
END;
END;

Related

Return ref_cursor from for loop of cursor object

I am trying to get a ref_cursor to be assigned to a variable inside a for loop then returned at the end of a function. The loop in going through a local cursor if it gets more than 1 result.
I have noted where the error occurs in the code. I am not sure how to create a loop where i can get a ref_cursor for the current point in the loop, assign it to a variable and then return it to the function. Could someone someone help me figure out how to do that? Below is my i-th attempt at logic based of reading around the google searches.
The error is "PLS-00382: expression is of wrong type" and i know that i obviously am not assigning the correct variably type based on this error but the code below with the error is an illustration of what I want to do and what I need help accomplishing.
FUNCTION GET_PARCEL(p_lat in number, p_long in number) return sys_refcursor
IS
v_distance number(10) := 100000000;
v_shortest_dist number(10) := v_distance;
v_centroid SDO_GEOMETRY;
v_rc_ref_cursor sys_refcursor;
v_ref_geom SDO_GEOMETRY := mdsys.SDO_GEOMETRY(2001, 8311, NULL, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY(120.3214, -10.7088));
cursor query_cursor is select * from PARCEL_TABLE where code = 20134;
BEGIN
for query_row in query_cursor loop
v_centroid := SDO_GEOM.SDO_CENTROID(query_row.geometry, 0.05);
IF (v_centroid is not null) then
v_distance := SDO_GEOM.SDO_DISTANCE(v_centroid, v_ref_geom, 0.05);
IF v_distance < v_shortest_dist THEN
v_shortest_dist := v_distance;
v_rc_ref_cursor := query_row; -- Error on this line
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE('Centroid is not initialised for some reason.');
END IF;
end loop;
return v_rc_ref_cursor;
END;
As far as I know, you cannot build up a cursor. Cursors are created and maintained by the database with connections to their source data, transaction and session context, and the like.
I would suggest you declare a type, instantiate it, build up the values in the type.
When you are done, create a cursor by selecting * from table (cast (variable as your_type)).
Munge the cursor into a ref_cursor and return that.
Pro tip is to remember you have data in your table and you can use it for logic. Turns out if I use the IDENTIFIER or ROWID of the row/s which i want then i can do a where clause into a ref cursor that looks up by IDENTIFIER or ROWID.
eg.
open v_rc_ref_cursor for select * from PARCEL_TABLE n where n.identifier = query_row.identifier;
super simple stuff :)

SQLite insert on android works only once

I'm with a problem on Delphi, i create a simple app to test the mobile power of RadStudio, I created a simple app that put some data into some inputs and then add it to database when button is clicked. I followed this Embarcadero tutorial as starting point
The problem is that I only get one entry added, then no more entries are added or the list is not refreshed. Below some code:
Table creation:
procedure TTabbedForm.logAfterConnect(Sender: TObject);
begin
log.ExecuteDirect('CREATE TABLE IF NOT EXISTS lista (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,idCons INTEGER,nome TEXT,kms INTEGER,kmsAlarme INTEGER,quantidade INTEGER,quantidadeAlarme INTEGER,data INTEGER,dataAlarme INTEGER,alarmeMsg TEXT)');
end;
Add button code:
procedure TTabbedForm.btnGravarClick(Sender: TObject);
begin
try
SQLQueryInsert.ParamByName('idCons').AsInteger := PopupBoxTipo.ItemIndex;
SQLQueryInsert.ParamByName('nome').AsString := PopupBoxTipo.Text;
SQLQueryInsert.ParamByName('kms').AsInteger := StrToInt(kmsEdit.Text);
SQLQueryInsert.ParamByName('quantidade').AsInteger := StrToInt(qtdEdit.Text);
SQLQueryInsert.ParamByName('data').AsInteger := DateTimeToUnix(dtaEvento.Date);
SQLQueryInsert.ExecSQL();
lista.Refresh;
LinkFillControlToField1.BindList.FillList;
except
on e: Exception do
begin
ShowMessage(e.Message);
end;
end;
end;
If you need some more code snippet, please ask!
Thanks in advance for any reply!
Try this method it works for me
procedure TData.InsertItem(someObject: TSomeObjectClass);
var
qry: TFDQuery;
begin
qry := CreateQry( 'insert into SomeObject(id, description, something)'+
' values (:id, :description, :something);', false);
qry.Params.ParamByName('id').AsInteger := someObject.id;
qry.Params.ParamByName('description').asstring := someObject.description;
qry.Params.ParamByName('something').asstring := someObject.something;
qry.Prepare;
qry.execsql;
qry.Free;
end;
I've put and object in the parameter but you can also put the data you want to insert seperatly

Can't use PLSQL ConvertToBlob inside a loop

I have a problem when trying to convert CLOB from a table to BLOB into another table.
Basically I'm looping inside a PLSQL array, the first call to DBMS_LOB.convertToBlob always works well, but the next iterations either create an empty blob or give me an error ORA-22275: invalid LOB locator specified, depending on whether I initialize my blob inside or outside the loop.
So, if I do :
BEGIN
FOR i IN 1 .. rs.COUNT
LOOP
DBMS_LOB.createTemporary (v_blob, TRUE);
DBMS_LOB.convertToBlob (v_blob,
rs (i).v_clob,
DBMS_LOB.LOBMAXSIZE,
v_in,
v_out,
DBMS_LOB.DEFAULT_CSID,
v_lang,
v_warning);
[...]
DBMS_LOB.freeTemporary(v_blob);
It converts the first blob well but only returns empty blobs for the other ones.
If I do:
BEGIN
DBMS_LOB.CREATETEMPORARY (v_blob, TRUE);
FOR i IN 1 .. rs.COUNT
LOOP
DBMS_LOB.convertToBlob(...);
It also converts the first blob well but I get the ORA-22275: invalid LOB locator specified error after the first iteration.
How could I avoid this? I can't seem to find good explanation for this. Thanks for your help!
Must be a NULL value problem. The CLOB must not be NULL. The following code gives me the error on the third round.
set serveroutput on
declare
TYPE rs_rec_type IS RECORD (
v_clob clob
);
TYPE rs_rec_table_type IS TABLE OF rs_rec_type INDEX BY pls_integer;
rs rs_rec_table_type;
v_blob blob;
v_in integer := 1;
v_out integer := 1;
v_lang integer := 0;
v_warning integer := 0;
BEGIN
rs(1).v_clob := 'foo';
rs(2).v_clob := 'bar';
rs(3).v_clob := null;
FOR i IN 1 .. rs.COUNT
LOOP
DBMS_LOB.createTemporary (v_blob, TRUE);
dbms_output.put_line('i='||i);
DBMS_LOB.convertToBlob (v_blob,
rs (i).v_clob,
DBMS_LOB.LOBMAXSIZE,
v_in,
v_out,
DBMS_LOB.DEFAULT_CSID,
v_lang,
v_warning);
dbms_output.put_line('done i='||i);
DBMS_LOB.freeTemporary(v_blob);
end loop;
end;
Output
Error report:
ORA-06502: PL/SQL: numeric or value error: invalid LOB locator specified: ORA-22275
ORA-06512: at "SYS.DBMS_LOB", line 991
ORA-06512: at line 20
06502. 00000 - "PL/SQL: numeric or value error%s"
*Cause:
*Action:
i=1
done i=1
i=2
done i=2
i=3
I experienced a similar problem when using temporary blobs within a loop.
I resolved it by initialising the in, out, lang and warning parameters each time.
James.
This worked for me:
declare
cursor note is
select id, rtf_clob
from rtf_data
where rtf_clob is not null
for update of rtf_blob;
l_blob blob;
l_amt integer := dbms_lob.lobmaxsize;
l_dest_offset integer := 1;
l_src_offset integer := 1;
l_csid integer := dbms_lob.default_csid;
l_ctx integer := dbms_lob.default_lang_ctx;
l_warn integer;
begin
for note_rec in note loop
l_blob := null;
l_amt := dbms_lob.lobmaxsize;
l_dest_offset := 1;
l_src_offset := 1;
l_csid := dbms_lob.default_csid;
l_ctx := dbms_lob.default_lang_ctx;
l_warn := null;
dbms_lob.createTemporary(l_blob, true);
dbms_lob.convertToBlob(l_blob,
note_rec.rtf_clob,
l_amt,
l_dest_offset,
l_src_offset,
l_csid,
l_ctx,
l_warn );
update rtf_data
set rtf_blob = l_blob
where note_rec.id = id;
dbms_lob.freeTemporary(l_blob);
end loop;
end;
/
Without reinitializing the variables inside the loop, only the first record created a blob.
This error might occur when the CLOB contains NULL.
This means the CLOB variable is passed NULL to the DBMS_LOB.convertToBlob
I had a similar problem to this and I figured something about DBMS_LOB.convertToBlob. The variables that you enter as dest_offset and src_offset change after the go through the procedure in question so you have to reset them after every iteration, in the case that you want to create multiple files.
I don't know if that helps directly with this problem in particular, but keep it in mind, for future reference, in case one uses DBMS_LOB.convertToBlob inside a loop.

TYPE cause ORA-06502: PL/SQL: numeric or value error

I have the following PL/SQL package:
CREATE OR REPLACE PACKAGE PKG_JCSJ
AS
TYPE record_organ_cant IS RECORD(CANT_CODE VARCHAR2(90),
ORGAN_ID VARCHAR2(90) ,
CANT_NAME VARCHAR2(90),
SUPP_TYPE VARCHAR2(20));
--TYPE array_organ_cant IS TABLE of PKG_JCSJ.record_organ_cant;
TYPE array_organ_cant IS TABLE of pub_organ_cant%ROWTYPE;
function fn_transe_organ_cant return PKG_JCSJ.array_organ_cant PIPELINED;
END PKG_JCSJ;
create or replace package body PKG_JCSJ is
function fn_transe_organ_cant return PKG_JCSJ.array_organ_cant PIPELINED
as
cursor cursor_organ_cant is select * from pub_organ_cant ;
record_o_c pub_organ_cant%rowtype;
record_o_c2 pub_organ_cant%rowtype;
cant_code VARCHAR2(90);
TYPE ref_cursor IS REF CURSOR;
array_column_value ref_cursor;
sp_cant_code VARCHAR2(90);
begin
open cursor_organ_cant;
loop
fetch cursor_organ_cant into record_o_c;
exit when cursor_organ_cant%notfound;
cant_code := record_o_c.cant_code;
if instr(cant_code, ',')>0 then
open array_column_value for select * from table(fn_split(cant_code));
loop
fetch array_column_value into sp_cant_code;
exit when array_column_value%notfound;
--DBMS_OUTPUT.put_line('---' || sp_cant_code);
record_o_c2.CANT_CODE := sp_cant_code;
record_o_c2.ORGAN_ID := record_o_c.ORGAN_ID;
record_o_c2.CANT_NAME := record_o_c.CANT_NAME;
record_o_c2.SUPP_TYPE := record_o_c.SUPP_TYPE;
--DBMS_OUTPUT.put_line('++++++' || record_o_c2.CANT_CODE);
PIPE ROW (record_o_c2);
end loop;
close array_column_value;
else
PIPE ROW (record_o_c);
end if;
end loop;
close cursor_organ_cant;
return;
end fn_transe_organ_cant;
begin
null;
end PKG_JCSJ;
Why is this statement failing?
TYPE array_organ_cant IS TABLE of PKG_JCSJ.record_organ_cant;
error info is ORA-06502: PL/SQL: numeric or value error. However, when I use the following statement, success!
TYPE array_organ_cant IS TABLE of pub_organ_cant%ROWTYPE;
record_organ_cant is same structure with TABLE pub_organ_cant, I have no idea why the former fails and the latter is successful, what's the difference?
then, package body as follow,
First of all, in your package body you don't have to use PKG_JCSJ. because its declared within the pacakge and should be accessible to any of its function like
create or replace package body PKG_JCSJ is
function fn_transe_organ_cant return array_organ_cant PIPELINED
....
Next, when you declare again you don't need PKG_JCSJ. like
CREATE OR REPLACE PACKAGE PKG_JCSJ
AS
TYPE record_organ_cant IS RECORD(CANT_CODE VARCHAR2(90),
ORGAN_ID VARCHAR2(90) ,
CANT_NAME VARCHAR2(90),
SUPP_TYPE VARCHAR2(20));
TYPE array_organ_cant IS TABLE of record_organ_cant;
function fn_transe_organ_cant return array_organ_cant PIPELINED;
END PKG_JCSJ;

How to call PL/SQL function in side a trigger

I am new to pl/sql. can any one tell me how to call pl/sql function inside a trigger.
I tired it but it gives an error when i try to run it.
DROP TRIGGER INTF_CONTROLLER_TREXE;
CREATE OR REPLACE TRIGGER INTF_CONTROLLER_TREXE
before insert ON INTF_CONTROLLER for each row
begin
BACKOFFICE_UPDATE();
end;
CREATE OR REPLACE FUNCTION BACKOFFICE_UPDATE
RETURN NUMBER IS
tmpVar NUMBER;
BEGIN
tmpVar := 0;
DBMS_OUTPUT.put_line ('HELLO');
RETURN tmpVar;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END BACKOFFICE_UPDATE;
I tried to run it using TOAD. it gives the following error
PLS-00221: 'BACKOFFICE_UPDATE' is not a procedure or is undefined
You need to store the result of your function call in a local variable
For example:
CREATE OR REPLACE TRIGGER INTF_CONTROLLER_TREXE
before insert ON INTF_CONTROLLER for each row
declare
dummy NUMBER;
begin
dummy := BACKOFFICE_UPDATE();
end;

Resources