How to Solve an Trigger Compilation Error? - sql

How can I solve this trigger compilation error?
SQL> create or replace trigger neg
2 before
3 insert
4 on tran
5 for each row
6
7 declare
8 no number;
9 begin
10 no:=new.no;
11 if no<=0 then
12 raise_application_error(-20002,'number is negative');
13 end if;
14 end;
15 /
Warning: Trigger created with compilation errors.
SQL> SHO ERROR Errors for TRIGGER NEG:
LINE/COL ERROR
-------- ----------------------------------------------------------------- 4/1 PL/SQL: Statement ignored 4/5 PLS-00201: identifier 'NEW.NO' must
be declared

Related

ORA-00904 INVALID IDENTIFIER oracle

I would like to update a table using a column that may not exists. I am doing this but getting an error, I tried to handle but still getting an exception. Is there a way to go about this? to update a table only if a column exists? I am a beginner in Oracle PL/SQL, any help would be appreciated. Thanks.
declare
column_not_exists_exception exception;
pragma exception_init (column_not_exists_exception , -06550);
begin
update table1
set column = case
when column_may_not_exists = 0 then 0
when column_may_not_exists = 1 then 1
else 0
end;
exception when column_not_exists_exception then
dbms_output.put_line('error column does not exists');
end;
The error I get is ORA-06550 and ORA-00904 : "column_may_not_exists" : invalid identifier , cause: usually a pl/sql compilation error
That is certainly a strange requirement, but since PL/SQL must be valid at compilation time, you can't reference a non-existent column directly.
Thus you can do the following
SQL> create table t ( x int, y int );
Table created.
SQL> insert into t values (0,0);
1 row created.
SQL>
SQL> set serverout on
SQL> declare
2 column_not_exists_exception exception;
3 pragma exception_init (column_not_exists_exception , -904);
4 begin
5 execute immediate '
6 update t
7 set y = case
8 when y = 0 then 10
9 when y = 1 then 20
10 else 30
11 end';
12 dbms_output.put_line('All good');
13 exception
14 when column_not_exists_exception then
15 dbms_output.put_line('error column does not exists');
16 end;
17 /
All good
PL/SQL procedure successfully completed.
SQL>
SQL> set serverout on
SQL> declare
2 column_not_exists_exception exception;
3 pragma exception_init (column_not_exists_exception , -904);
4 begin
5 execute immediate '
6 update t
7 set z = case
8 when z = 0 then 10
9 when z = 1 then 20
10 else 30
11 end';
12 dbms_output.put_line('All good');
13 exception
14 when column_not_exists_exception then
15 dbms_output.put_line('error column does not exists');
16 end;
17 /
error column does not exists
PL/SQL procedure successfully completed.

Trying to execute function in PL/SQL but I am getting error

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.

is there a function without an input but return something

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>

ORA-06531 after Oracle upgrade

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.

Oracle DDL execution with immediate mode and errors

After doing about two hours' worth of research on various issues with execute immediate and error handling, I don't think I've encountered exactly the problem I am about to present. I have reduced my issue to the sample below. The issue is:
When I execute a procedure create in immediate mode with the create text in a variable and a syntax error in the create text, the execute immediate call throws an error indicating that it failed. But I can't get at the underlying error or its text.
However, when I create the same proc directly in sqlplus (w/o intermediate mode), getting the error works perfectly.
So, how does one get at the error that causes immediate mode to fail?
I have interspersed the output with my comments (MOP) and reduced the number of blank lines:
SQL*Plus: Release 10.2.0.1.0 - Production on Mon Mar 25 15:57:06 2013
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> set serveroutput on
SQL> declare
2 eSQL varchar(568);
3 begin
4 eSQL := 'create or replace procedure MOPMOP
5 as
6 begin
7 select 1 from dual;
8 end;
9 ';
10 execute immediate eSQL;
11 end;
12 /
ERROR:
ORA-24344: success with compilation error
ORA-06512: at line 10
Warning: PL/SQL compilation errors.
This is good. There's a compilation error. So, now let me ask what that compilation error is:
SQL> show errors;
No errors.
This is no good. There's a compilation error. What was it!?!?!? Contrast that with:
SQL> create or replace procedure MOPMOP
2 as
3 begin
4 select 1 from dual;
5 end;
6 /
Warning: Procedure created with compilation errors.
This is good. There's a compilation error. So, now let me ask what that compilation error is:
SQL> show errors;
Errors for PROCEDURE MOPMOP:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/5 PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
And this is good. There's a compilation error. And now I know what is is.
So, how do I get intermediate mode to spit out the underlying (00428) error?
when you run show errors on its own it will show the errors for any prior "create" / "alter" that sqlplus itself did, which is this case is nothing (as it was hidden from sqlplus because of the dynamic SQL)
you have to expcitly say you want to see the errors of the procedure for this case:
SQL> declare
2 eSQL varchar(568);
3 begin
4 eSQL := 'create or replace procedure MOPMOP
5 as
6 begin
7 select 1 from dual;
8 end;
9 ';
10 execute immediate eSQL;
11 end;
12 /
ERROR:
ORA-24344: success with compilation error
ORA-06512: at line 10
Warning: PL/SQL compilation errors.
SQL> show errors procedure mopmop
Errors for PROCEDURE MOPMOP:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/5 PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
as the create ran server side and not through sqlplus, sqlplus didn't know about the failure, so couldnt fetch the errors correctly.
also if you had a prior failure, it would retain that:
SQL> create or replace procedure MOPMOP2
2 as
3 begin
4 select 1 from dual;
5 end;
6 /
Warning: Procedure created with compilation errors.
SQL> declare
2 eSQL varchar(568);
3 begin
4 eSQL := 'create or replace procedure MOPMOP
5 as
6 begin
7 select 1 from dual;
8 end;
9 ';
10 execute immediate eSQL;
11 end;
12 /
ERROR:
ORA-24344: success with compilation error
ORA-06512: at line 10
Warning: PL/SQL compilation errors.
SQL> show errors
Errors for PROCEDURE MOPMOP2:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/5 PLS-00428: an INTO clause is expected in this SELECT statement
SQL>
You cannot use select 1 from dual... in PL/SQL. Must use select into. In both cases you are creating PL/SQL procedures not some SQL script.
declare
x number;
begin
select 1 into x from dual;
end;
/
declare
procedure MOPMOP
as
x number;
begin
select 1 into x from dual;
dbms_output.put_line(x);
end MOPMOP;
begin
MOPMOP;
end;
/
Avoid ORA-24344 - although I probably would never use dynamic sql for this:
declare
eSQL varchar(568);
x number;
begin
eSQL := 'create or replace procedure MOPMOP as
begin
select 1 into x from dual;
end;';
execute immediate eSQL;
EXCEPTION WHEN OTHERS THEN NULL;
end;
/