Disabling trigger only for specific oracle procedure - oracle

We have a requirement to disable a trigger only for a specific procedure run in ORACLE.
We have Table A and Table B.
The trigger is designed to insert into Table B for each insert or update of Table A.
The procedure makes entries to Table A.
How to enable/disable trigger in procedure?
The above link explains how to enable and disable the trigger during the procedure.
But my requirement is during this procedure run, if there are other inserts to Table A, then the trigger should run as expected.
Is this possible? Please help on how to achieve the same if possible.

You can use the DBMS_APPLICATION_INFO and SYS_CONTEXT to set any parameter in your procedure and then check for that parameter in the TRIGGER to see if you should take any action in the trigger or not as follows:
Table description:
SQL> DESC AA;
Name Null? Type
----------------------------------------- -------- ----------------------------
COL1 NOT NULL NUMBER
SQL>
Trigger code:
SQL> CREATE OR REPLACE TRIGGER AA_TRG BEFORE
2 INSERT OR UPDATE ON AA
3 FOR EACH ROW
4 BEGIN
5 IF SYS_CONTEXT(
6 'USERENV',
7 'ACTION'
8 ) = 'DISABLE_TRIGGER' THEN
9 DBMS_OUTPUT.PUT_LINE('TRIGGER DISABLED');
10 ELSE
11 DBMS_OUTPUT.PUT_LINE('TRIGGER ENABLED');
12 END IF;
13
14 DBMS_APPLICATION_INFO.SET_ACTION(ACTION_NAME => NULL);
15 END;
16 /
Trigger created.
SQL>
Disabled trigger procedure code:
SQL> CREATE OR REPLACE PROCEDURE AA_DISABLED_TRIGGER_PROC AS
2 BEGIN
3 DBMS_APPLICATION_INFO.SET_ACTION(ACTION_NAME => 'DISABLE_TRIGGER');
4 INSERT INTO AA VALUES ( 3 );
5
6 ROLLBACK;
7 END;
8 /
Procedure created.
SQL>
Enabled trigger procedure code:
SQL> CREATE OR REPLACE PROCEDURE AA_ENABLED_TRIGGER_PROC AS
2 BEGIN
3 INSERT INTO AA VALUES ( 3 );
4
5 ROLLBACK;
6 END;
7 /
Procedure created.
SQL>
Calling the procedures:
SQL>
SQL> SET SERVEROUT ON
SQL> BEGIN
2 AA_ENABLED_TRIGGER_PROC;
3 END;
4 /
TRIGGER ENABLED
PL/SQL procedure successfully completed.
SQL>
SQL> SET SERVEROUT ON
SQL> BEGIN
2 AA_DISABLED_TRIGGER_PROC;
3 END;
4 /
TRIGGER DISABLED
PL/SQL procedure successfully completed.
SQL>
SQL> SET SERVEROUT ON
SQL> BEGIN
2 AA_ENABLED_TRIGGER_PROC;
3 END;
4 /
TRIGGER ENABLED
PL/SQL procedure successfully completed.
SQL>

Not possible. If trigger is disabled, then it is disabled and won't work.
But, if you alter the table and add a column which says who is inserting rows into it, then you could use trigger's WHEN clause to distinguish this procedure from other inserters and either fire the trigger or not. It means, of course, that trigger remains enabled all the time.

Related

How to run select statement after stored procedure run ORACLE

I am new to Oracle, trying to run select statement after my stored procedure and failing. Here I am trying to return rows or any dummy data after my store procedure is executed, because my end process needs a return data for sure to make it consider as successful run. Is there any way I can trick it here is what I tried and failed.
EX:
BEGIN
note.name;
END;
/
SELECT * from hello.table where rownum=1;
Error:
ERROR [HY000] [Microsoft][ODBC Oracle Wire Protocol driver][Oracle]ORA-06550: line 4, column 1:
PLS-00103: Encountered the symbol "/"
Activity ID: xxxxxx-xxx-xxx-xxx-xxxxxx
Show return a single row after completion of stored procedure
Code you posted looks OK. Demo:
SQL> create or replace procedure p_test as
2 begin
3 null;
4 end;
5 /
Procedure created.
SQL> begin
2 p_test;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> select * from dept where rownum = 1;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
SQL>
Therefore, what exactly is your problem? What result do you expect?
If "at once" (as you commented) means that everything should be part of a PL/SQL block, then you'd declare a variable which is capable of holding the whole row, and then just select into it. rownum = 1 condition prevents too_many_rows error.
SQL> set serveroutput on
SQL>
SQL> declare
2 l_dept dept%rowtype;
3 begin
4 p_test;
5 select * into l_dept from dept where rownum = 1;
6 dbms_output.put_line(l_dept.deptno ||', '|| l_dept.dname ||', '|| l_dept.loc);
7 end;
8 /
10, ACCOUNTING, NEW YORK
PL/SQL procedure successfully completed.
SQL>

Restrict creation of table on sunday in oracle

Question: create a pl/sql using a trigger to restrict creation of any
table on Sunday
I tried
CREATE OR REPLACE TRIGGER sunday_trigger
BEFORE CREATE ON ALSPRD
FOR EACH ROW
DECLARE
v_day DATE := TRUNC(SYSDATE);
BEGIN
IF TO_CHAR(v_day,'DY')IN ('SUN') THEN
REVOKE create table from harsh;
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Error is:'||SQLERRM);
END;
It creating error ORA-30506: system triggers cannot be based on tables or views
I'd suggest a different approach.
Connected as SYS, create a trigger that prevents user (scott in my example) to create anything on desired day (I'll use Monday so that I could test whether it works as planned).
SQL> show user
USER is "SYS"
SQL>
SQL> create or replace trigger sunday_trigger
2 before create on scott.schema
3 begin
4 if to_char(sysdate, 'DY', 'nls_date_language = english') = 'MON'
5 then
6 raise_application_error(-20000, 'You can not create any objects on Monday');
7 end if;
8 end;
9 /
Trigger created.
Let's test it:
SQL> connect scott/tiger
Connected.
SQL> select to_char(sysdate, 'DY', 'nls_date_language = english') today from dual;
TODAY
------------
MON
SQL> create table so_test (id number);
create table so_test (id number)
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-20000: You can not create any objects on Monday
ORA-06512: at line 4
SQL> create or replace procedure p_test is
2 begin
3 null;
4 end;
5 /
create or replace procedure p_test is
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-20000: You can not create any objects on Monday
ORA-06512: at line 4
SQL>
Let's pretend it is tomorrow (Tuesday):
SQL> connect sys as sysdba
Enter password:
Connected.
SQL> select sysdate from dual;
SYSDATE
--------
21.06.21
SQL> alter system set fixed_date = '22.06.21';
System altered.
SQL> connect scott/tiger
Connected.
SQL> select to_char(sysdate, 'DY', 'nls_date_language = english') today from dual;
TODAY
------------
TUE
SQL> create table so_test (id number);
Table created.
SQL> create or replace procedure p_test is
2 begin
3 null;
4 end;
5 /
Procedure created.
SQL>
Looks OK to me.
Revoke user rights to create tables from harsh.
Create another user <OWNER_PROC> with rights to create tables.
Make a procedure <CREATE_TABLE_PROC> that creates tables and in this procedure you can make any logic.
Grant execute on <OWNER_PROC>.<CREATE_TABLE_PROC> to harsh.

Can i disable a trigger inside a trigger in oracle?

I have 2 triggers and two tables.
One(trigger) is to insert inside one column in the other table when a row in first table is inserted, the other one prevent insert and update in that column.
I want to know if there is a way i can disable the second trigger that prevents the insert/update during the execution of first trigger.
This is how I understood the question. See if it helps.
Sample tables:
SQL> create table test (id number);
Table created.
SQL> create table test_2 (id number);
Table created.
A trigger on test_2 which prevents inserts:
SQL> create or replace trigger trg2
2 before insert or update on test_2
3 for each row
4 begin
5 raise_application_error(-20000, 'Not allowed');
6 end;
7 /
Trigger created.
Does it work?
SQL> insert into test_2 (id) values (1);
insert into test_2 (id) values (1)
*
ERROR at line 1:
ORA-20000: Not allowed
ORA-06512: at "SCOTT.TRG2", line 2
ORA-04088: error during execution of trigger 'SCOTT.TRG2'
Yes, it works.
Now, a trigger on test which is supposed to a) disable trg2 trigger and b) insert value into test_2. A straightforward code would then be
SQL> create or replace trigger trg1
2 before insert on test
3 for each row
4 begin
5 execute immediate 'alter trigger trg2 disable';
6 insert into test_2 (id) values (:new.id);
7 end;
8 /
Trigger created.
Let's test it:
SQL> insert into test (id) values (1);
insert into test (id) values (1)
*
ERROR at line 1:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SCOTT.TRG1", line 2
ORA-04088: error during execution of trigger 'SCOTT.TRG1'
Aha. Can't COMMIT in a trigger. Where is it? In dynamic SQL's alter trigger - it is a DDL and it implicitly commits. How to "fix" it? Make it (a trigger) an autonomous transaction:
SQL> create or replace trigger trg1
2 before insert on test
3 for each row
4 declare
5 pragma autonomous_transaction;
6 begin
7 execute immediate 'alter trigger trg2 disable';
8 insert into test_2 (id) values (:new.id);
9 end;
10 /
Trigger created.
SQL> insert into test (id) values (1);
insert into test (id) values (1)
*
ERROR at line 1:
ORA-06519: active autonomous transaction detected and rolled back
ORA-06512: at "SCOTT.TRG1", line 6
ORA-04088: error during execution of trigger 'SCOTT.TRG1'
That's another error; it says that - if we have an autonomous transaction - we have to either commit or roll back. Let's commit (because that's probably what you'd want to do):
SQL> create or replace trigger trg1
2 before insert on test
3 for each row
4 declare
5 pragma autonomous_transaction;
6 begin
7 execute immediate 'alter trigger trg2 disable';
8 insert into test_2 (id) values (:new.id);
9 commit;
10 end;
11 /
Trigger created.
SQL> insert into test (id) values (100);
1 row created.
SQL> select * From test;
ID
----------
100
SQL> select * from test_2;
ID
----------
100
SQL>
Right; now it works.
I suggest you re-read comments posted below your question, see this example and choose what to do.

Can we call procedure or function from anonymous block in oracle?

Can i call a pl/sql object by procedure or function from within an anonymous block?
This is a very frequent interview question.
Thanks
Yes:
SQL> set serveroutput on
SQL> --
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
SQL> show user;
USER is "C##TEST"
SQL> --
SQL> CREATE OR REPLACE PROCEDURE myproc
2 IS
3 BEGIN
4 dbms_output.put_line('myproc: OK');
5 END;
6 /
Procedure created.
SQL> --
SQL> show errors
No errors.
SQL> --
SQL> CREATE OR REPLACE FUNCTION myfunc RETURN VARCHAR2
2 IS
3 BEGIN
4 return 'myfunc: OK';
5 END;
6 /
Function created.
SQL> --
SQL> show errors
No errors.
SQL> --
SQL> begin
2 myproc;
3 end;
4 /
myproc: OK
PL/SQL procedure successfully completed.
SQL> --
SQL> declare
2 myvar VARCHAR2(50);
3 begin
4 select myfunc into myvar from dual;
5 dbms_output.put_line(myvar);
6 end;
7 /
myfunc: OK
PL/SQL procedure successfully completed.

Unable to find procedure in DBA_PROCEDURES view

I have created a procedure :
create or replace procedure gg as
begin
insert into book values ('prashant','prashant','prashant');
commit;
end;
/
Procedure has been created successfully.Now i want to check the package name for the corresponding procedure but i am not able to do so.
I am using the below query :
> SELECT *
FROM SYS.DBA_PROCEDURES
WHERE procedure_name ='gg';
Its giving 0 rows selected.Please help.
NOTE Please look at the UPDATE section for correct answer.
The procedure name cannot be in lower case in the DBA_PROCEDURES view. Use upper case, or apply UPPER function.
SELECT *
FROM SYS.DBA_PROCEDURES
WHERE procedure_name ='GG';
UPDATE
The only case when you could have the name in lower case is if you enclose it within double-quotation marks while compiling.
For example,
SQL> CREATE OR REPLACE
2 PROCEDURE "p"
3 AS
4 BEGIN
5 NULL;
6 END;
7 /
Procedure created.
SQL> SELECT object_name, procedure_name, object_type FROM user_procedures where procedure_name='p';
no rows selected
SQL>
But still the above view will not return any result for PROCEDURE_NAME.
Reason
PROCEDURE_NAME column will only have the procedure name for the procedures which are part of a PACKAGE. For STAND ALONE PROCEDURES you need to use OBJECT_NAME.
SQL> -- stand alone procedure in lower case
SQL> CREATE OR REPLACE
2 PROCEDURE "p"
3 AS
4 BEGIN
5 NULL;
6 END;
7 /
Procedure created.
SQL>
SQL> -- package
SQL> CREATE OR REPLACE
2 PACKAGE test_p
3 IS
4 PROCEDURE p;
5 END test_p;
6 /
Package created.
SQL>
SQL> -- package body with a procedure
SQL> CREATE OR REPLACE
2 PACKAGE BODY test_p
3 IS
4 PROCEDURE p
5 IS
6 BEGIN
7 NULL;
8 END;
9 END test_p;
10 /
Package body created.
SQL>
SQL> SELECT object_name, procedure_name, object_type FROM user_procedures;
OBJECT_NAME PROCEDURE_NAME OBJECT_TYPE
--------------- --------------- ---------------
TEST_P P PACKAGE
p PROCEDURE
TEST_P PACKAGE
SQL>
So, as you can see, the procedure_name is only having the package's procedure, however the stand-alone procedure is only listed under object_name.
The query I use is:
SELECT * FROM User_Procedures WHERE NVL(Procedure_Name,Object_Name) = 'PROCNAME';

Resources