Using MSSQL - I can drop synonym only if it exist:
DROP SYNONYM (Transact-SQL)
But in Oracle (11g) drop synonym causes my script to error if it doesn't exit, is there a way to mimic the MSSQL it exist?
You can use a PLSQL anonymous block:
begin
execute immediate 'drop synonym YOUR_SYNONYM';
exception
when others then
if sqlcode != -1434 then
raise;
end if;
end;
/
It will drop your synonym if it exists. If it doesn't exist, it will just suppress the error. It will raise any error other than "synonym does not exist" to the caller.
Apparently you can write: CREATE OR REPLACE SYNONYM
You can use a pragma to define an exception which you can then handle.
Assuming you are doing something in a loop...
declare
NOSYN exception;
pragma exception_init ( NOSYN, -1434 );
/* 1434 is the Oracle error for synonym does not exist */
begin
/*
* Loop here where you synonym name gets assigned to the variable mysyn
*/
begin
execute immediate 'drop synonym '||mysyn;
exception
when NOSYN then
dbms_output.put_line( 'Synonym does not exist... skipping' );
end;
end loop;
end;
/
Related
I am trying to implement Trigger that raises an User Defined Error Message and does not allow the update and Insert operation in the database.I am new to pl/sql i refereed some code from the internet and try to implement.My code is running is fine as i can not update/insert into database but still i am unable to get my user defined message and also i am getting this warning.
Warning: Trigger created with compilation errors ?
This is the table :
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER(5)
NAME VARCHAR2(20)
SALARY NUMBER(10)
DEPOT_ADDRESS VARCHAR2(15)
here is my code :
create or replace trigger cleaner_before_update_insert
for update or insert on cleaner
compound trigger
count binary_integer;
before statement is
begin
count:=0;
end before statement;
after each row is
begin
count :=count +1;
end after each row;
after statement is
begin
if count > 0 then
raise_application_error( -20001,'Update/insert operation can not be completed ');
end if;
end after statement;
end cleaner_before_update;
/
can anyone help me figure out what is the problem here and way to fix it.
thanks in advance.
Even after compilation of the code it is giving me this error.
ORA-06512: at "SYSTEM.CLEANER_BEFORE_UPDATE_INSERT", line 18
ORA-04088: error during execution of trigger
'SYSTEM.CLEANER_BEFORE_UPDATE_INSERT'
There are couple of problems with your TRIGGER block.
The name of the Trigger cleaner_before_update_insert does not match with the cleaner_before_update after the final end statement.
COUNT is an SQL keyword which is not allowed to be used as a variable in PL/SQL.You would receive the error - Error(10,11): PLS-00204: function or pseudo-column 'COUNT' may be used inside a SQL statement only
So, here is the modified code.
CREATE OR REPLACE TRIGGER cleaner_before_update_insert FOR UPDATE OR
INSERT ON cleaner compound TRIGGER
v_count binary_integer;
before STATEMENT
IS
BEGIN
v_count:=0;
END before STATEMENT;
AFTER EACH row
IS
BEGIN
v_count :=v_count +1;
END AFTER EACH row;
AFTER STATEMENT
IS
BEGIN
IF v_count > 0 THEN
raise_application_error( -20001,'Update/insert operation can not be completed ');
END IF;
END AFTER STATEMENT;
END cleaner_before_update_insert;
/
My whole intention to catch exception,WRONG parameter is NOT CATCHING exception.
Here is the code:
CREATE OR REPLACE PROCEDURE list_emp (p_emp_id IN employees.employee_id%TYPE,
p_dept_id IN employees.department_id%TYPE)
IS
CURSOR c1 IS
SELECT *
FROM EMPLOYEES
WHERE EMPLOYEE_ID=p_emp_id
AND DEPARTMENT_ID=p_dept_id;
emp_rec c1%ROWTYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO emp_rec;
EXIT WHEN c1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(emp_rec.employee_id||' '||emp_rec.first_name||' '||emp_rec.last_name);
END LOOP;
CLOSE c1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No Record Found ');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('No Record Found ');
END;
When the cursor is opened and fetched with the wrong parameter that does not match any row from the corresponding table, the following line
EXIT WHEN c1%NOTFOUND;
cause the plsql procedure to terminate (because there were no rows found). Hence no exception is raised.
If you do want to display some sort of output you can do the following instead
IF c1%FOUND THEN
dbms_output.put_line('Record Found');
ELSE
dbms_output.put_line('Finished/Done');
EXIT;
END IF;
If you want to raise an error after looping through a cursor that returns no rows, then you're going to have to use a counter to work out how many rows have been processed, and then you can do something if no rows have been processed.
Something like:
create or replace procedure list_emp (p_emp_id in employees.employee_id%type,
p_dept_id in employees.department_id%type)
is
cursor c1 is
select employee_id,
first_name,
last_name
from employees
where employee_id = p_emp_id
and department_id = p_dept_id;
v_count number := 0;
begin
for emp_rec in c1
loop
v_count := v_count + 1;
dbms_output.put_line(emp_rec.employee_id||' '||emp_rec.first_name||' '||emp_rec.last_name);
end loop;
if v_count = 0 then
raise no_data_found;
end if;
exception
when no_data_found then
dbms_output.put_line('No Record Found.');
raise;
when others then
dbms_output.put_line('An error occurred: '||sqlerrm);
raise;
end;
/
A few notes:
I converted your cursor loop into a cursor-for-loop; you don't need to worry about declaring the record type and also Oracle handles the opening and closing of the cursor for you.
I added raise; to each of your exception handlers - in general, having when others then null (which is effectively what your original code was doing - no errors are raised to the calling code) is a bad idea. I added the raise to the no_data_found condition as that wasn't doing anything either; typically, if you have an exception condition, you want it to do something to let the calling code know there was a problem (not always, of course; sometimes you don't want the processing to stop if a particular error condition is met).
Your cursor was selecting all columns, but in your procedure, you were only using three of them. I've therefore amended the cursor so that it only pulls back those three columns.
Don't rely on dbms_output in your production code. Code that calls this procedure won't see anything populated in dbms_output, unless it explicitly looks for it - and that's not something I've ever seen in any production code, outside of Database tools (eg. SQL*Plus, Toad, etc). I've left this in your procedure as I've a feeling this is a learning exercise for you, but please don't think that this is in any way acceptable in production code.
You're passing p_emp_id in as a parameter - typically, that's the primary key of the employees table. If that's the case, then there's no need for the cursor for loop at all - you could do it by using select ... into ... instead, like so:
.
create or replace procedure list_emp (p_emp_id in employees.employee_id%type,
p_dept_id in employees.department_id%type)
is
v_emp_id employees.employee_id%type;
v_first_name employees.first_name%type;
v_last_name employees.last_name%type;
begin
select employee_id,
first_name,
last_name
into v_emp_id,
v_first_name,
v_last_name
from employees
where employee_id = p_emp_id
and department_id = p_dept_id;
dbms_output.put_line(emp_rec.employee_id||' '||emp_rec.first_name||' '||emp_rec.last_name);
exception
when no_data_found then
dbms_output.put_line('No Record Found.');
raise;
when others then
dbms_output.put_line('An error occurred: '||sqlerrm);
raise;
end;
/
Alternatively, just pass back a ref cursor:
create or replace procedure list_emp (p_emp_id in employees.employee_id%type,
p_dept_id in employees.department_id%type,
p_ref_cur out sys_refcursor)
is
begin
open p_ref_cur for select employee_id,
first_name,
last_name
from employees
where employee_id = p_emp_id
and department_id = p_dept_id;
-- No need for an exception handler here since you're not storing the error details anyway.
-- By not having an error handler, any error will automatically be raised up to the calling code
-- and it will have the correct error stack trace info (e.g. the line number the error occurred,
-- rather than the line the error was reraised from
end;
/
And to run the ref cursor in SQL*Plus (or as a script in Toad/SQL Developer/etc), you do the following:
-- create a variable outside of PL/SQL to hold the ref cursor pointer (this is a SQL*Plus command):
variable rc refcursor;
-- populate our ref cursor variable with the pointer. Note how we pass it in as a bind variable
begin
list_emp(p_emp_id => 1234,
p_dept_id => 10,
p_ref_cur => :rc);
end;
/
-- finally, print the contents of the ref cursor.
print rc;
I'm trying to catch an exception within my anonymous PL/SQL block
DECLARE
...
BEGIN
FOR herstell_row IN (
...
)
LOOP
...
DECLARE
table_does_not_exists exception;
pragma exception_init( table_does_not_exists, -942 );
BEGIN
INSERT INTO SMART_MONITORING_MACHINE_NAV_B (
MACHINE,
NAVIGATION_LEVEL_ID
)
SELECT
old_binding.MACHINE,
pv_id
FROM
SMART_MACHINE_NAV_BINDING old_binding
WHERE
old_binding.NAVIGATION_LEVEL_ID = herstell_row.HENAME1;
EXCEPTION
WHEN table_does_not_exists THEN null;
END;
END LOOP;
END;
I know the table SMART_MACHINE_NAV_BINDING doesn't exist in my case, so I need the nested anonymous block to ignore its code. But I always get this error:
Error report -
ORA-06550: line 41, column 14:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 33, column 10:
PL/SQL: SQL Statement ignored
You can't compile code with non-existent table, but you can try to execute it using EXECUTE EMMEDIATE:
DECLARE
...
BEGIN
FOR herstell_row IN (
...
)
LOOP
...
DECLARE
table_does_not_exists exception;
pragma exception_init( table_does_not_exists, -942 );
BEGIN
execute immediate
'INSERT INTO SMART_MONITORING_MACHINE_NAV_B (
MACHINE,
NAVIGATION_LEVEL_ID
)
SELECT
old_binding.MACHINE,
pv_id
FROM
SMART_MACHINE_NAV_BINDING old_binding
WHERE
old_binding.NAVIGATION_LEVEL_ID = :P' using herstell_row.HENAME1;
EXCEPTION
WHEN table_does_not_exists THEN null;
END;
END LOOP;
END;
Also you don't need exceptions here, you can check existence of a table using system view:
declare
table_created number;
begin
select count(*)
into table_created
from all_tables
where table_name = ...
and owner = ...;
if table_created > 0 then
execute immediate 'insert into ...';
end if;
end;
More information about EXECUTE IMMEDIATE statement: http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/executeimmediate_statement.htm#LNPLS01317
Oracle does not know this error table_does_not_exists it is user defined, so you should handle in when others then, for eg.
Exception
When Others then
null;
-- or at this time you can raise your error table_does_not_exists
raise table_does_not_exists;
-- and handle it in another parent block
end;
Exception
when table_does_not_exists then
null;
end;
Am getting this error 'PL/SQL: ORA-00942: table or view does not exist' in Oracle 11G when I try to runt his portion of my script. It seems the select statement isn't parsing the name of the variable from the cursor. Need help to ensure this can read the table name variable from the cursor.
DECLARE
ITEM_ERROR NUMBER;
CNT_SITE VARCHAR2(46);
CURSOR C_SITEID IS
SELECT OBJECTNAME,ATTRIBUTENAME FROM MAXATTRIBUTE WHERE ATTRIBUTENAME LIKE 'SITE%' GROUP BY OBJECTNAME,ATTRIBUTENAME, COLUMNNAME;
SITEIDRec C_SITEID%RowType;
BEGIN
BEGIN
OPEN C_SITEID;
LOOP
FETCH C_SITEID into SITEIDRec;
EXIT WHEN C_SITEID %NOTFOUND;
BEGIN
SELECT COUNT(SITEID) into CNT_SITE FROM SITEIDRec.OBJECTNAME
WHERE SITEID IN ('COLLEGE NANO SCI ENG-TGCM','FREESCALE-BALAZS','TGCM-GLOBAL FOUNDRIES','INTL RECTIFIER-TGM','TGCM-DMOS5','TGCM-IMFT','TGCM-TRIQUINT','GP-TRIQUINT');
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
END LOOP;
--COMMIT;
CLOSE C_SITEID;
--COMMIT;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
END;
--COMMIT;
EXCEPTION
WHEN OTHERS THEN
MSG_TEXT := SUBSTR(SQLERRM,1,200);
--COMMIT;
raise;
END;
I think you have FROM TableName missing in your query and hence it's rightly complaining.
SELECT COUNT(SITEID) into SITEIDRec.OBJECTNAME
WHERE SITEID IN
('COLLEGE NANO SCI ENG-TGCM','FREESCALE-BALAZS',
'TGCM-GLOBAL FOUNDRIES','INTL RECTIFIER-TGM','TGCM-DMOS5',
'TGCM-IMFT','TGCM-TRIQUINT','GP-TRIQUINT');
Please correct your query by adding the From TableName.
EDIT: Try using EXECUTE IMMEDIATE as below
EXECUTE IMMEDIATE 'SELECT COUNT(SITEID) into CNT_SITE FROM '
|| SITEIDRec.OBJECTNAME ||
' WHERE SITEID IN (''COLLEGE NANO SCI ENG-TGCM'',''FREESCALE-BALAZS'',
''TGCM-GLOBAL FOUNDRIES'',''INTL RECTIFIER-TGM'',''TGCM-DMOS5'',
''TGCM-IMFT'',''TGCM-TRIQUINT'',''GP-TRIQUINT'')';
I am using sql developer, and have added a constraint to one of my tables.
constraint valid_gender check(gender in ('M','F','I','T'))
When I try to add an entry with say 'x' for gender using a plsql procedure, it fails with constraint violation (as it should).
I want to add a "Catch" to the plsql procedure so that if valid_gender is voilated I can raise_application_error specific to it. Is this possible?
Oracle will raise an exception that says:
ORA-02290: check constraint (yourschema.valid_gender) violated
You can catch that in an exception handler and raise your own exception instead using raise_application_error in a couple of ways.
1) You can specifically trap the ORA-02290 exception like this:
declare
e_check_violated exception
pragma exception_init (e_check_violated, -2290);
begin
insert ...
exception
when e_check_violated then
if sqlerrm like '%(yourschema.valid_gender)%' then
raise_application_error(-20001,'Invalid gender');
else
raise;
end if;
end;
2) You can trap all exceptions and inspect them:
begin
insert ...
exception
when others then
if sqlerrm like 'ORA-02290:%(yourschema.valid_gender)%' then
raise_application_error(-20001,'Invalid gender');
else
raise;
end if;
end;
In a large application it is quite common to have an exception handling procedure to generalise this and look up the constraint-specific message in a table.
use anonym block in your code...
BEGIN
INSERT or update...
EXCEPTION
WHEN dup_val_on_index THEN
RISE...
END;
You could just test it first:
if gender_value not in ('M','F','I','T') then
raise_application_error...
end if;