I upgraded my database from Oracle 10 to 11.2. The problem I face is that my geometry in tables don't work any more. My SQL is:
Select
GEOMETRYID, COORDCOUNT, CREATIONDATE, QUALITYID,
SDO_UTIL.TO_WKTGEOMETRY(SDO_CS.TRANSFORM(SDO_UTIL.SIMPLIFY(GEOMETRY, 1, 0.0000005), 27700)) as "WKT"
FROM
NWKGEOMETRY
WHERE
DELETIONDATE IS NULL;
AND SDO_GEOMETRY.GET_GTYPE(GEOMETRY)=2 AND SDO_UTIL.GETNUMVERTICES(GEOMETRY)>2;
and I get an error:
ORA-06531: Reference to uninitialized collection
If I remove TRANSFORM function then all works fine. What could be wrong?
This error:
ORA-06531: Reference to uninitialized collection
means that you have a collection that is not initialized before you use it, for example:
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
SQL> ed
Wrote file afiedt.buf
1 CREATE OR REPLACE TYPE t_employee AS OBJECT(
2 id number,
3 name VARCHAR2(300),
4 CONSTRUCTOR FUNCTION t_employee RETURN SELF AS RESULT
5* )
SQL> /
Type created.
SQL> ed
Wrote file afiedt.buf
1* CREATE OR REPLACE TYPE t_employees AS TABLE OF t_employee
SQL> /
Type created.
SQL> ed
Wrote file afiedt.buf
1 DECLARE
2 l_emp t_employee;
3 l_emps t_employees;
4 BEGIN
5 for i in (SELECT employee_id, first_name
6 FROM employees)
7 loop
8 l_emp := t_employee(i.employee_id, i.first_name);
9 l_emps.extend();
10 l_emps(l_emps.COUNT) := l_emp;
11 end loop;
12 DBMS_OUTPUT.put_line(l_emps(4).name);
13* END;
SQL> /
DECLARE
*
ERROR at line 1:
ORA-06531: Reference to uninitialized collection
ORA-06512: at line 9
As you can see, I have the ORA-06531 error, that's because I haven't initialized the l_emps variable, I have to add l_emps := t_employees();:
SQL> ed
Wrote file afiedt.buf
1 DECLARE
2 l_emp t_employee;
3 l_emps t_employees;
4 BEGIN
5 l_emps := t_employees();
6 for i in (SELECT employee_id, first_name
7 FROM employees)
8 loop
9 l_emp := t_employee(i.employee_id, i.first_name);
10 l_emps.extend();
11 l_emps(l_emps.COUNT) := l_emp;
12 end loop;
13 DBMS_OUTPUT.put_line(l_emps(4).name);
14* END;
SQL> /
David
PL/SQL procedure successfully completed.
So take a look at the sources of all these PL/SQL procedures, the problem is in them.
Related
CREATE OR REPLACE FUNCTION f_dohvati_post
(
post_id int)
RETURN postovi%ROWTYPE AS redak postovi%ROWTYPE;
BEGIN
SELECT *
INTO redak
from postovi
WHERE id = post_id;
RETURN redak;
END;
I tried executing function with
Exec f_dohvati_post(1);
And i am getting this error ->
Error starting at line : 29 in command -
BEGIN f_dohvati_post(1); END;
Error report -
ORA-06550: line 1, column 7:
PLS-00221: 'F_DOHVATI_POST' is not a procedure or is undefined
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I don't have your table so I created one:
SQL> create table postovi as select deptno id, dname, loc from dept;
Table created.
SQL> create or replace function f_dohvati_post(post_id int)
2 return postovi%rowtype
3 as
4 redak postovi%rowtype;
5 begin
6 select *
7 into redak
8 from postovi
9 where id = post_id;
10 return redak;
11 end;
12 /
Function created.
It is a function, so you don't "execute" it, but:
SQL> select f_dohvati_post(10) from dual;
select f_dohvati_post(10) from dual
*
ERROR at line 1:
ORA-00902: invalid datatype
SQL>
Whoops! Won't work either! So, what to do? Create your own type:
SQL> create or replace type t_row as object
2 (id number,
3 dname varchar2(10),
4 loc varchar2(10));
5 /
Type created.
SQL> create or replace type t_tab as table of t_row;
2 /
Type created.
SQL> create or replace function f_dohvati_post(post_id int)
2 return t_tab
3 as
4 redak t_tab;
5 begin
6 select t_row(id, dname, loc)
7 bulk collect into redak
8 from postovi
9 where id = post_id;
10 return redak;
11 end;
12 /
Function created.
SQL> select * from table(f_dohvati_post(10));
ID DNAME LOC
---------- ---------- ----------
10 ACCOUNTING NEW YORK
SQL>
Now it works.
I am trying to troubleshoot a PL/SQL package. I found a similar example to explain my question as I am new to learning PL/SQL and how a cursor works with a procedure.
So for example:
CREATE OR REPLACE PROCEDURE emp_by_job (
p_job VARCHAR2,
p_emp_refcur IN OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN p_emp_refcur FOR SELECT empno, ename FROM emp WHERE job = p_job;
END;
In this I see that p_job is defined as VARCHAR2. Then the SQL selects from EMP where job = p_job. All we've defined p_job as is VARCHAR2, not mapped to a field anywhere. How does the cursor know what to do with job = p_job, where does p_job's value come from?
Thank you!
A procedure doesn't do anything when it is compiled, it needs to be called/invoked. The value for p_job will be passed when the procedure is called. In the example below, emp_by_job is invoked from an anonymous pl/sql block with a value for the argument p_job of 'MANAGER'.
koen>CREATE OR REPLACE PROCEDURE emp_by_job (
2 p_job VARCHAR2,
3 p_emp_refcur IN OUT SYS_REFCURSOR
4 )
5 IS
6 BEGIN
7 OPEN p_emp_refcur FOR SELECT empno, ename FROM emp WHERE job = p_job;
8 END;
9* /
Procedure EMP_BY_JOB compiled
koen>set serveroutput on size 999999
koen>DECLARE
2 TYPE emp_t IS REF CURSOR;
3 l_emp emp_t;
4 l_emprow emp%ROWTYPE;
5 BEGIN
6 emp_by_job(p_job => 'MANAGER',p_emp_refcur => l_emp);
7 LOOP
8 FETCH
9 l_emp
10 INTO
11 l_emprow.empno,
12 l_emprow.ename;
13 EXIT
14 WHEN l_emp%notfound;
15 dbms_output.put_line(l_emprow.empno || ' ' || l_emprow.ename);
16 END LOOP;
17 END;
18* /
7698 BLAKE
7782 CLARK
7566 JONES
PL/SQL procedure successfully completed.
koen>
I've searched on stackoverflow and other sources, but haven't found anything useful.
I have to implement a procedure that receives a row (hence "%rowtype") from Reservation table as a parameter.
The table's name is Reservation (as attributes: id_Reservation, id_Room, price, etc).
I created an anonymous block to create the var_reservation variable, which will serve as the parameter to the procedure:
CREATE OR REPLACE PROCEDURE priceCheckout(var_reservation reservation%ROWTYPE) IS
l_idReservation NUMBER;
l_idRoom NUMBER;
prie INT;
date1 DATE;
date2 DATE;
ex exception;
BEGIN
l_idReservation := var_reservation.id_reservation;
(...)
END;
But this is wrong. How can I correct this?
If you do it correctly, it works. Have a look at the following example based on Scott's DEPT table:
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------------- --------------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL> set serveroutput on
Procedure:
SQL> create or replace procedure p_test (var_row dept%rowtype)
2 is
3 l_dname dept.dname%type;
4 begin
5 l_dname := var_row.dname;
6
7 dbms_output.put_line('Department name = ' || l_dname);
8 end;
9 /
Procedure created.
Testing:
SQL> declare
2 l_row dept%rowtype;
3 begin
4 select *
5 into l_row
6 from dept
7 where deptno = 10;
8
9 p_test(l_row);
10 end;
11 /
Department name = ACCOUNTING
PL/SQL procedure successfully completed.
SQL>
Saying that "this is wrong" is difficult to debug. It is not an Oracle error message so ... unless you specify what is "this" and, possibly, edit the question and post copy/paste of your own SQL*Plus session (like I did) so that we'd see what you did and how Oracle responded, YOYO.
This stored procedure call returns a single varchar2 type value. The issue is that it comes back in a refcursor. I need to get the ID value and assign it to a variable instead of printing it to the console.
var r refcursor;
DECLARE
BEGIN
P_PACKAGE.INSERT_INVOICE(
IN_INVOICE_TYPE => L_INVOICE.INVOICE_TYPE,
OUTPUT => :R);
END;
/
print r;
Exactly as you said - you need to assign it to a variable. Here's an example based on Scott's schema.
SQL> create or replace procedure p_rc (par_deptno in number, par_rc out sys_refcursor)
2 is
3 begin
4 open par_rc for select ename, sal
5 from emp
6 where deptno = par_deptno;
7 end;
8 /
Procedure created.
Let's test it; pay attention to lines #4, 5 (declaration of variables) and #10 (fetch into those variables):
SQL> declare
2 l_rc sys_refcursor;
3 -- declare variables which will get values returned by refcursor
4 l_ename emp.ename%type;
5 l_sal emp.sal%type;
6 begin
7 p_rc(10, l_rc);
8
9 loop
10 fetch l_rc into l_ename, l_sal;
11 exit when l_rc%notfound;
12 dbms_output.put_line(rpad(l_ename, 10, ' ') ||': '|| l_sal);
13 end loop;
14 end;
15 /
CLARK : 2450
KING : 5001
MILLER : 1300
PL/SQL procedure successfully completed.
SQL>
I wouldn't define the REFCURSOR in SQL*Plus as you've shown it. Assuming that your REFCURSOR was opened with a statement similar to
SELECT ID
FROM SOME_TABLE
WHERE SOMEFIELD = some_value
then your PL/SQL code should look something like
DECLARE
aString VARCHAR2(2000);
rc SYS_REFCURSOR;
BEGIN
P_PACKAGE.INSERT_INVOICE(
IN_INVOICE_TYPE => L_INVOICE.INVOICE_TYPE,
OUTPUT => rc);
FETCH rc
INTO aString;
DBMS_OUTPUT.PUT_LINE('aString = ''' || aString || '''');
END;
CREATE OR REPLACE FUNCTION FN_MULTAS_TOTAL
RETURN INTEGER
IS
V_TOTAL INT;
BEGIN
SELECT SUM(MULTA)
INTO V_TOTAL
FROM DETALLE_ARRIENDO;
RETURN V_TOTAL;
END;
im working on SQL Developer 11 and i have to call it with
exec FN_MULTAS_TOTAL;
and get an integer value
No problem with such a function:
SQL> create or replace function fn_multas_total
2 return integer
3 is
4 v_total int;
5 begin
6 select sum(multa)
7 into v_total
8 from detalle_arriendo;
9 return v_total;
10 end;
11 /
Function created.
However, you don't call it with exec - it is used in SQL*Plus or SQL Developer or some other tools which support it; it is a "shortcut" for an anonymous begin-end PL/SQL block:
SQL> exec p_test
PL/SQL procedure successfully completed.
SQL> begin
2 p_test;
3 end;
4 /
PL/SQL procedure successfully completed.
It is used for procedures, not functions. You can't just
SQL> begin
2 detalle_arriendo;
3 end;
4 /
detalle_arriendo;
*
ERROR at line 2:
ORA-06550: line 2, column 3:
PLS-00221: 'DETALLE_ARRIENDO' is not a procedure or is undefined
ORA-06550: line 2, column 3:
PL/SQL: Statement ignored
SQL>
which means that you have to declare a variable and fetch function's result into it, e.g.
SQL> declare
2 l_result number;
3 begin
4 l_result := fn_multas_total;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>
Usually, we use functions as
SQL> select fn_multas_total from dual;
FN_MULTAS_TOTAL
---------------
100
SQL>
If you desperately want to use exec, then you still have to declare a variable and
SQL> var result number
SQL> exec :result := fn_multas_total;
PL/SQL procedure successfully completed.
SQL> print :result
RESULT
----------
100
SQL>