how to solve this error
create or replace package pg1
as
procedure p1(p_deptno in number);
type t is table of emp%rowtype
index by binary_integer;
end pg1;
create or replace package body pg1
as
procedure p1(p_deptno in number)
as
v_emp t;
v_dep exception;
begin
begin
select * bulk collect into v_emp from emp where deptno=p_deptno;
if p_deptno=10 then
raise v_dep;
end if;
for i in v_emp.first..v_emp.last
loop
insert into pg values(v_emp(i).empno, v_emp(i).ename, v_emp(i).job, v_emp(i).mgr, v_emp(i).hiredate, v_emp(i).sal, v_emp(i).comm, v_emp(i).deptno);
end loop;
exception
when v_dep then
raise_application_error(-20200,'my exception raised');
raise value_error;
end
when value_error then/*here getting error*/
dbms_output.put_line('value error');
end;
end p1;
end pg1;
end;
23/1 PLS-00103: Encountered the symbol "WHEN" when expecting one
of
the following:
;
First always try to evaluate what error does oracle throws. Oracle errors are very descriptive inmost of the cases. Here if you see carefully it always points to the exact line number too. Hope you will try to debug next time onwards :)
CREATE OR REPLACE PACKAGE pg1
AS
PROCEDURE p1(
p_deptno IN NUMBER);
type t
IS
TABLE OF emp%rowtype INDEX BY binary_integer;
END pg1;
CREATE OR REPLACE PACKAGE body pg1
AS
PROCEDURE p1(
p_deptno IN NUMBER)
AS
v_emp t;
v_dep EXCEPTION;
BEGIN
BEGIN
SELECT * bulk collect INTO v_emp FROM emp WHERE deptno=p_deptno;
IF p_deptno=10 THEN
raise v_dep;
END IF;
FOR i IN v_emp.first..v_emp.last
LOOP
INSERT
INTO pg VALUES
(
v_emp(i).empno,
v_emp(i).ename,
v_emp(i).job,
v_emp(i).mgr,
v_emp(i).hiredate,
v_emp(i).sal,
v_emp(i).comm,
v_emp(i).deptno
);
END LOOP;
EXCEPTION
WHEN v_dep THEN
raise_application_error(-20200,'my exception raised');
raise value_error;
END; -- Missed semi colon here
WHEN value_error THEN
dbms_output.put_line('value error');
END;
END p1;
END pg1;
END;
Related
if i have 3 insert statements in my plsql code.
lets assume them as insert_1, insert_2, insert_3.
my conditions be like : if insert_1 statement successfully executed then automatically insert_3 should be executed as well as if insert_3 executed successfully then insert_1 also should be executed automatically.
if both insert_1 and insert_3 fails then only insert_2 should be executed.
please write plsql code for this requirement.
You can create a package for this:
create a package and inside package body you try something like this.
create or replace PACKAGE BODY PKG_INSERT_QUERY AS
P_ERR_CODE number;
procedure finalPro
is
begin
P_ERR_CODE := 0;
insert into a values('a');
commit;
EXCEPTION WHEN OTHERS THEN ROLLBACK;
DBMS_OUTPUT.PUT_LINE('ERROR ' ||SQLERRM);
P_ERR_CODE := 1;
if(P_ERR_CODE < 1 )then
secondQ;
IF(P_ERR_CODE < 1) THEN
thirdQ;
END IF;
END IF;
end;
procedure secondQ
as
begin
insert into B values('B');
commit;
EXCEPTION WHEN OTHERS THEN ROLLBACK;
DBMS_OUTPUT.PUT_LINE('ERROR ' ||SQLERRM);
P_ERR_CODE := 2;
end;
procedure thirdQ
as
begin
insert into C values('C');
commit;
EXCEPTION WHEN OTHERS THEN ROLLBACK;
DBMS_OUTPUT.PUT_LINE('ERROR ' ||SQLERRM);
P_ERR_CODE := 3;
end;
end;
I'm trying to create a code in which i delete a student from my table by specifying his nr_matr, but if i don't have that nr_matr in my table then i want to trow an exception.
this is my code:
CREATE OR REPLACE PACKAGE manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type);
END manager_faculty;
/
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type) IS
BEGIN
DELETE from student
WHERE nr_matricol=nr_matr;
EXCEPTION
WHEN no_data_found THEN
SELECT COUNT(*) INTO counter FROM student WHERE nr_matricol=nr_matr;
IF counter = 0 THEN
raise_application_error (-20001, 'There is no student with the number' || nr_matr);
END IF;
END delete_stud;
END manager_faculty;
/
set serveroutput on;
BEGIN
manager_faculty.delete_stud(125);
END;
/
When i'm trying to compile my code it says that the package body was created whit compilation errors. What am i doing wrong?
The error is PLS-00201: identifier 'COUNTER' must be declared and you can find this out by running SHOW ERRORS; after trying to compile your package body.
You can fix it like this:
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type)
IS
counter INT;
BEGIN
DELETE FROM student
WHERE nr_matricol=nr_matr;
EXCEPTION
WHEN no_data_found THEN
SELECT COUNT(*)
INTO counter
FROM student
WHERE nr_matricol=nr_matr;
IF counter = 0 THEN
raise_application_error (
-20001,
'There is no student with the number' || nr_matr
);
END IF;
END delete_stud;
END manager_faculty;
/
SHOW ERRORS;
However, the code won't run as you expect as DELETE FROM will not throw an exception if it does not delete any rows. You will need to check SQL%ROWCOUNT:
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type)
IS
BEGIN
DELETE from student
WHERE nr_matricol=nr_matr;
IF SQL%ROWCOUNT = 0 THEN
raise_application_error (
-20001,
'There is no student with the number' || nr_matr
);
END IF;
END delete_stud;
END manager_faculty;
/
Aside from using SQL%ROWCOUNT as answered by MTO, you can also use SQL%NOTFOUND.
%NOTFOUND yields TRUE if an INSERT, UPDATE, or DELETE statement affected no rows, or a SELECT INTO statement returned no rows. Otherwise, it yields FALSE.
CREATE OR REPLACE PACKAGE BODY manager_faculty IS
PROCEDURE delete_stud (nr_matr student.nr_matricol%type)
IS
BEGIN
DELETE from student
WHERE nr_matricol=nr_matr;
IF SQL%NOTFOUND THEN
raise_application_error (
-20001,
'There is no student with the number' || nr_matr
);
END IF;
END delete_stud;
END manager_faculty;
You can read here, if you want to know other attributes of SQL Cursor.
I want to create a script for my oracle DB, which drops tables. If the table does not exist, the script won't exit as fail, just print a text: "does not exists".
The script is the following:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE mytable';
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
END;
I want to drop a lot of table in one script, and I don't want to write these lines more than once.
Is there any way, to write it to a procedure or function which gets a parameter (the name of the table), and call this procedure in that script?
Maybe something like this:
drop_table_procedure('mytableA');
drop_table_procedure('mytableB');
Or maybe a procedure, which gets an undefined size list (like in java: String ... table names):
drop_tables_procedure('mytableA','mytableB');
Please give me some examples.
Thanks!
Yes, you can declare a "temporary" procedure in an anonymous PL/SQL block:
DECLARE
PROCEDURE drop_if_exists(p_tablename VARCHAR)
IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE '||p_tablename;
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
END;
BEGIN
drop_if_exists('TABLE_1');
drop_if_exists('TABLE_2');
END;
/
in execute immediate you need add name of database object.
here's the script
create table t1 (col1 int);
create table t2 (col1 int);
create procedure drop_my_table(av_name varchar2)
as
begin
EXECUTE IMMEDIATE 'DROP TABLE '||av_name;
DBMS_Output.Put_Line(' table dropped');
EXCEPTION WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_Output.Put_Line(' table not exists');
ELSE
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
END IF;
end drop_my_table;
declare
type array_t is varray(2) of varchar2(30);
atbls array_t := array_t('t1', 't2');
begin
for i in 1..atbls.count loop
drop_my_table(atbls(i));
end loop;
end;
You can use below one also
create or replace PROCEDURE drop_if_exists(p_tablename in VARCHAR)
IS
v_var1 number;
begin
select 1 into v_var1 from user_tables where table_name=upper(p_tablename);
if v_var1=1
then
EXECUTE IMMEDIATE 'DROP TABLE '||p_tablename;
DBMS_Output.Put_Line(' table dropped');
else
DBMS_Output.Put_Line(' table not exist');
end if;
exception
when others then
DBMS_Output.Put_Line(' Unknown exception while dropping table');
RAISE;
end;
Call procedure
begin
drop_if_exists('emp');
end;
/
I am creating a trigger below, as long as I insert something already existed in the table, then print other wise do nothing.
create or replace trigger TR_insert
Before INSERT On A
For each row
DECLARE
l_act integer;
l_name varchar(30);
l_minute integer;
Begin
select count(1) into l_act
From A
Where Activity=:new.Activity;
if(l_act>0) then
DBMS_OUTPUT.PUT_LINE ('There is duplicate.');
else
DBMS_OUTPUT.PUT_LINE('');
end if;
end;
It is working fine when I insert something existed, but when I insert new item, then it gives out error "SQL Error: ORA-01403: no data found", why is that please?
You're getting the error because your select does not return any value for your new item. The below shud work.
begin
select count(1) into l_act
From A
Where Activity=:new.Activity;
if(l_act>0) then
DBMS_OUTPUT.PUT_LINE ('There is duplicate.');
end if;
exception
when NO_DATA_FOUND then
DBMS_OUTPUT.PUT_LINE('');
end;
I have a set of table names, let say 150. Each table have mail_id column, now I want to search one mail_id in all of the table. For that I wrote one Plsql block. When I loop through the set of table some tables do not exists so it raises an exception. I have exception handling block to handle that exception. Now I want to loop entire table even though it raise an exception? Any idea? Actually my block didn't handle that particular exception!
declare
my_mail_id varchar2(50):='xyaksj#jsm.com';
tmp_table varchar2(125);
type varchar_collector is table of varchar2(255);
var varchar_collector;
table_does_not_exist exception;
PRAGMA EXCEPTION_INIT(table_does_not_exist, -00942);
begin
for cntr in (select table_name from user_tables)
loop
tmp_table:=cntr.table_name;
dbms_output.put_line(tmp_table);
for mail in (select email_address from tmp_table where lower(email_address) like '%my_mail_id%' )
loop
dbms_output.put_line(tmp_table);
end loop;
end loop;
exception
when no_data_found then
dbms_output.put_line('email address not found');
WHEN table_does_not_exist then
dbms_output.put_line('table dose not exists');
WHEN OTHERS THEN
--raise_application_error(-20101, 'Expecting at least 1000 tables');
IF (SQLCODE = -942) THEN
--DBMS_Output.Put_Line (SQLERRM);
DBMS_Output.Put_Line ('in exception');--this exception not handled
ELSE
RAISE;
END IF;
end;
Just handle your exceptions in anonymous block inside the loop.
DECLARE
my_mail_id VARCHAR2(50) := 'xyaksj#jsm.com';
tmp_table VARCHAR2(125);
TYPE varchar_collector IS TABLE OF VARCHAR2(255);
var varchar_collector;
table_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_does_not_exist, -00942);
BEGIN
FOR cntr IN (SELECT table_name FROM user_tables)
LOOP
BEGIN
tmp_table := cntr.table_name;
dbms_output.put_line(tmp_table);
FOR mail IN (SELECT email_address
FROM tmp_table
WHERE lower(email_address) LIKE '%my_mail_id%')
LOOP
dbms_output.put_line(tmp_table);
END LOOP;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('email address not found');
WHEN table_does_not_exist THEN
dbms_output.put_line('table dose not exists');
WHEN OTHERS THEN
--raise_application_error(-20101, 'Expecting at least 1000 tables');
IF (SQLCODE = -942)
THEN
--DBMS_Output.Put_Line (SQLERRM);
DBMS_Output.Put_Line('in exception'); --this exception not handled
ELSE
RAISE;
END IF;
END;
END LOOP;
END;
If you're selecting from user_tables and finding that some of them do not exist then you're probably trying to query tables that are in the recycle bin (their names begin BIN$).
If so, change your query to:
select table_name
from user_tables
where dropped = 'NO';
You should replace your second cursor with a call to execute immediate also, constructing the query by concatenating in the table_name not just using a variable as the table name, and you might as well construct the query as:
select count(*)
from table_name
where lower(email_address) like '%my_mail_id%'
and rownum = 1;
That way you'll retrieve a single record that is either 0 or 1 to indicate whether the email address was found, and no need for error handling.
try below code...
DECLARE
foo BOOLEAN;
BEGIN
FOR i IN 1..10 LOOP
IF foo THEN
GOTO end_loop;
END IF;
<<end_loop>> -- not allowed unless an executable statement follows
NULL; -- add NULL statement to avoid error
END LOOP; -- raises an error without the previous NULL
END;