We have two "AFTER LOGON ON DATABASE" triggers, each owned by different DBA-owned schemas and serving different purposes. Trigger A is consistently getting executed prior to trigger B. We need to reverse that and ensure that trigger B fires first.
According to the documentation, we supposedly could use "PRECEDES ..." syntax to control this, but when used with a database trigger it throws ORA-25025: cannot specify PRECEDES clause, so that's a dead-end.
Any ideas how to control which of these AFTER LOGON triggers fires first?
Does anybody know if dbms_ddl.set_trigger_firing_property can do this with some secret property value?
PRECEDES is about editioning triggers. Check out FOLLOWS
SQL> create or replace
2 trigger trg1
3 after logon on scott.schema
4 begin
5 null;
6 end;
7 /
Trigger created.
SQL>
SQL>
SQL> create or replace
2 trigger trg2
3 after logon on scott.schema
4 follows trg1
5 begin
6 null;
7 end;
8 /
Trigger created.
SQL>
or at database level
SQL> create or replace
2 trigger trg1
3 after logon on database
4 begin
5 null;
6 end;
7 /
Trigger created.
SQL>
SQL>
SQL> create or replace
2 trigger trg2
3 after logon on database
4 follows trg1
5 begin
6 null;
7 end;
8 /
Trigger created.
Related
I need to create a script to delete some data in a database, the table doesn't have the CASCADE constraint and I don't have the right to edit them.
So I'm trying to create a TRIGGER to simulate a Cascade delete on a table (and I will remove it just after the script get executed).
Here is my trigger:
CREATE TRIGGER delete_workspace_on_delete_result
BEFORE DELETE ON RESULT
FOR EACH ROW
BEGIN
DELETE FROM WORKSPACE WHERE workspace_result_id = :old.id;
END;
/
I don't understand why it's not working, I just follow the Oracle documentation but I have this error:
Error report -
ERROR: syntax error at or near "BEGIN"
Position: 87
I'm not used to Oracle but can't find a way to make this work by my own.
I don't see anything wrong, it works. Though:
won't work on Oracle 11g or lower because trigger name is too long (can be max 30 characters)
will work on 12c and above
consider using create or replace; if it exists and you try to create it again, it'll fail
Demo on 11g:
SQL> CREATE TABLE workspace (workspace_result_id NUMBER);
Table created.
SQL> CREATE TABLE result (id NUMBER);
Table created.
SQL> CREATE TRIGGER delete_workspace_on_delete_result
2 BEFORE DELETE
3 ON RESULT
4 FOR EACH ROW
5 BEGIN
6 DELETE FROM WORKSPACE
7 WHERE workspace_result_id = :old.id;
8 END;
9 /
CREATE TRIGGER delete_workspace_on_delete_result
*
ERROR at line 1:
ORA-00972: identifier is too long
SQL> CREATE TRIGGER delete_workspace_on_del_result
2 BEFORE DELETE
3 ON RESULT
4 FOR EACH ROW
5 BEGIN
6 DELETE FROM WORKSPACE
7 WHERE workspace_result_id = :old.id;
8 END;
9 /
Trigger created.
SQL>
I recently moved my database to a new server (both Oracle 11g).
In the new host, there is a weird behavior, that whenever I run something like:
create or replace test_trigger
before insert or update
on test_table
for each row
begin
select 1 from dual;
end;
/
The trigger created is invalid without any error in log. I tried to recompile, it still invalid.
It only happen with the function "create or replace". If I drop the trigger and re-create again, it would be valid.
My question is, did I config something incorrectly? How can I check it? Thank you.
Code you posted won't compile, not in any Oracle database I know. Why? Wrong syntax.
Here's a demonstration:
SQL> create or replace test_trigger
2 before insert or update
3 on test_table
4 for each row
5 begin
6 select 1 from dual;
create or replace test_trigger
*
ERROR at line 1:
ORA-00922: missing or invalid option
SQL> end;
SP2-0042: unknown command "end" - rest of line ignored.
SQL> /
So, what's wrong with it?
create (or replace) wants to know what you're going to create. "test_trigger"? As far as Oracle is concerned, that could be "mickey_mouse" and the result will be the same. It is the trigger keyword that is missing
SELECT in PL/SQL requires an INTO clause, so that you could store the result into something
in order to be able to do that, you have to declare a variable
Here's code that, actually, compiles:
SQL> create or replace trigger test_trigger --> this
2 before insert or update
3 on test_table
4 for each row
5 declare
6 l_dummy number; --> this
7 begin
8 select 1
9 into l_dummy --> this
10 from dual;
11 end;
12 /
Trigger created.
SQL>
So, it seems that you misinterpret reality.
I want to know what are the thumb rules/guidlines to write the logs of a stored procedure(application programs). Normally we use 2 methods:
1) Use UTL_FILE package to write the logs into files(separate files for every run).
2) Use Log4pl package to write the the different logs(dignostic,Error,Warning or Fatal) into a table.
Almost for every procedure we use above 2 methods depending on what we are writing. Like for fatal error we use Log4pl and for some information display(like which record its processing we write that in file).
Would like to know how other organizations maintaining logs ? Do they also follow aboe 2 methods or they use only one? on what basis its been decided?
Note: I am looking for logs writting only for application programming not for Databse.
Any suggestions or links to blogs would be great. Thanks.
one more way you can implement logging mechanism in oracle application-
-> splunk
UTL_FILE isn't really going to scale well for writing log files, eg
SQL> create table log_table (
2 s timestamp default systimestamp,
3 m varchar2(1000)
4 );
Table created.
SQL>
SQL> set timing on
SQL> begin
2 for i in 1 .. 10000 loop
3 insert into log_table (m) values ('My message');
4 commit;
5 end loop;
6 end;
7 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.62
SQL>
SQL> declare
2 f utl_file.file_type;
3 begin
4 f := utl_file.fopen('TMP','logfile.dat','W');
5 for i in 1 .. 10000 loop
6 utl_file.put_line(f,to_char(systimestamp)||' '||'My message');
7 utl_file.fflush(f);
8 end loop;
9 utl_file.fclose(f);
10 end;
11 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:30.58
Now you might be thinking "I'll just remove the utl_file.fflush(f) call" which indeed will make it run in a comparable time to the database table. But the time when you most need that logging information is when your program crashes - and if it crashes, and you have not flushed, then you run the risk of losing the recent logging information that is critical for knowing why your program crashed.
When I execute the following trigger code it is compiled. Then after inserting data, serveroutput says '1 row inserted' trigger result ('User Example has insrted a data') didn't displayed.
Then after execution of another PL/SQL the previous trigger result will appears on display. What should i do to solve this issue?
Here is the trigger and the insertion command and also the results,
/
SET SERVEROUTPUT ON;
CREATE OR REPLACE TRIGGER BTR_SUPERHEROS
BEFORE INSERT ON SUPERHEROS
FOR EACH ROW
ENABLE
DECLARE
V_USER VARCHAR2(30);
BEGIN
SELECT USER INTO V_USER FROM DUAL;
DBMS_OUTPUT.ENABLE();
DBMS_OUTPUT.PUT_LINE('USER:' ||V_USER||' HAS INSERTED A DATA');
END;
/
RESULT - Trigger BTR_SUPERHEROS compiled
INSERT INTO SUPERHEROS VALUES('SUPERMAN');
RESULT - 1 row inserted. (Didn't Shows the DBMS_OUTPUT)
You need to set serveroutput on in the client application (SQL*Plus, SQL Developer etc) in the session where you run a statement, otherwise it won't know that you want it fetch and display the output buffer when the statement completes. The set server output on prior to creating the trigger is just a client setting and doesn't set it permanently for the trigger.
Please confirm whether your test case was run from a single session, like this:
SQL*Plus: Release 12.1.0.1.0 Production on Tue Aug 15 08:17:48 2017
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Last Successful login time: Tue Aug 15 2017 08:14:08 +01:00
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL> SET SERVEROUTPUT ON;
SQL>
SQL> CREATE OR REPLACE TRIGGER BTR_SUPERHEROS
2 BEFORE INSERT ON SUPERHEROS
3 FOR EACH ROW
4 ENABLE
5
6 DECLARE
7 V_USER VARCHAR2(30);
8 BEGIN
9 SELECT USER INTO V_USER FROM DUAL;
10 DBMS_OUTPUT.ENABLE();
11 DBMS_OUTPUT.PUT_LINE('USER:' ||V_USER||' HAS INSERTED A DATA');
12 END;
13 /
Trigger created.
SQL> INSERT INTO SUPERHEROS VALUES('SUPERMAN');
USER:WILLIAM HAS INSERTED A DATA
1 row created.
Note also that it is not recommended to call dbms_output.enable. From the documentation:
You should generally avoid having application code invoke either the DISABLE Procedure or ENABLE Procedure because this could subvert the attempt of an external tool like SQL*Plus to control whether or not to display output.
You can also assign values using the assignment := operator instead of a select into statement. The trigger could therefore be written as:
create or replace trigger btr_superheros
before insert on superheros
for each row
enable
declare
v_user user_users.username%type := sys_context('userenv', 'current_schema');
begin
dbms_output.put_line('User: ' ||v_user||' inserted value '''||:new.name||'''');
end;
/
I'm Learning Oracle and wanted to try creating a trigger. I tried this example form a book in sqlplus.
SQL> CREATE OR REPLACE TRIGGER policy_bull BEFORE insert or update
2 ON emp
3 FOR EACH ROW
4 BEGIN
5 :new.salary := 200;
6 END
7 /
ERROR at line 1:
ORA-04089: cannot create triggers on objects owned by SYS
even though I logged in as SYS using
sqlplus "sys/oracle as sysdba"
You need to type / on a blank line to tell SQLPLUS to run the statement.
Oracle forbids creating triggers on objects owned by SYS.
Did you create the table emp as SYS? You probably want to be a regular user to do that. emp doesn't sound like a system table.
I think a semi-colon is missing after END.
Also mention SYS.emp
SQL> CREATE OR REPLACE TRIGGER policy_bull BEFORE insert or update
2 of SALARY on EMP
3 FOR EACH ROW
4 BEGIN
5 :new.salary := 200;
6 END
7 /
you have to type the column where the "NEW SALARY" is ppl its SALARY so ...or update of SALARY on EMP...