Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Sushant.

Asked: October 18, 2001 - 1:08 pm UTC

Last updated: May 05, 2004 - 9:18 am UTC

Version: 8.1.5

Viewed 1000+ times

You Asked

1)Is it possible to fire a trigger the moment the time is 12.am.

2)in a ddl trigger which is something is lik this create or replace trigger tr after create on database......

what iam doing is is just adding a row ina table saying a create statement is fired.
what i want is it should show what type of an object was created say a table or view or sequence .how do i trap what object was created.

3)
i have a normal (emp table) as provided by oracle .

i want the output somewhat lik this

empno ename sal empno ename sal empno ename sal
101 aaaa 2222 102 rrr 3333 103 rttt 2666
104 gggg 5555 104 fff 7777 105 yytt 7777

4)
In a table say i have 50 rows how do i get the rows between the 15th and 45th row or say from 15throw to 50th row




and Tom said...

1) close to 12am, it will not be assured to be exactly 12am.

See dbms_job in the supplied packages guide.

2) see chapter 14 of your application developer guide for 815, it lists all of the System Defined Event Attributes such as:

dictionary_obj_type VARCHAR(20)

Type of the dictionary object on which the DDL operation occurred.

INSERT INTO event_table ('This object is a ' || sys.dictionary_obj_type);

dictionary_obj_name VARCHAR(30)

Name of the dictionary object on which the DDL operation occurred.

INSERT INTO event_table ('Changed object is ' || sys.dictionary_obj_name');

dictionary_obj_owner VARCHAR(30)

Owner of the dictionary object on which the DDL operation occurred.

INSERT INTO event_table ('object owner is' || sys.dictionary_obj.owner');


3) not really possible in sql, you need a report writing tool to massage the data after you fetch it.

4)
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:127412348064 <code>
...

Rating

  (6 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

reply to question 3

mike, October 18, 2001 - 4:31 pm UTC

Tom, I have not tested this statement, but I think it would produce the desired results.

SELECT a.empno
,a.ename
,a.sal
,b.empno
,b.ename
,b.sal
,c.empno
,c.ename
,c.sal
FROM (SELECT rownum rn, empno, ename, sal
FROM emp
ORDER by empno) a
,(SELECT rownum rn, empno, ename, sal
FROM emp
ORDER by empno) b
,(SELECT rownum rn, empno, ename, sal
FROM emp
ORDER by empno) c
WHERE MOD(a.rn,3) = 1
AND MOD(b.rn,3) = 2
AND MOD(c.rn,3) = 0
AND a.rn = b.rn + 1
AND a.rn = c.rn + 2
ORDER by a.empno;

Tom Kyte
October 18, 2001 - 6:40 pm UTC

well, you would need some outer joins AND the inline views need work. Here is your concept:

scott@ORA717DEV.US.ORACLE.COM> SELECT a.empno
2 ,a.ename
3 ,a.sal
4 ,b.empno
5 ,b.ename
6 ,b.sal
7 ,c.empno
8 ,c.ename
9 ,c.sal
10 FROM (select rownum rn, a.*
11 from (SELECT empno, ename, sal
12 FROM emp
13 ORDER by empno) a
14 ) a,
15 (select rownum rn, b.*
16 from (SELECT empno, ename, sal
17 FROM emp
18 ORDER by empno) b
19 ) b,
20 (select rownum rn, c.*
21 from (SELECT empno, ename, sal
22 FROM emp
23 ORDER by empno) c
24 ) c
25 WHERE b.rn(+) = a.rn + 1
26 AND c.rn(+) = a.rn + 2
27 and mod(a.rn,3) = 1
28 ORDER by a.empno;

EMPNO ENAME SAL EMPNO ENAME SAL EMPNO ENAME SAL
---------- -------- ----- ---------- -------- ----- ---------- -------- -----
7369 A 800 7499 ALLEN 1600 7521 WARD 1250
7566 JONES 2975 7654 MARTIN 1250 7698 BLAKE 2850
7782 CLARK 2450 7788 SCOTT 3000 7839 KING 5000
7844 TURNER 1500 7876 ADAMS 1100 7900 JAMES 950
7902 FORD 3000 7934 MILLER 1300

But, while this is technically FEASIBLE, I deemed it as impractical (sometimes, I just have to say "no, you don't really want to do that").

there are other ways to do it as well using decode, group bys and in 8i r2 (816) and up -- using analytic functions....

More info in ddl database trigger

A reader, May 04, 2004 - 10:58 am UTC

Hi Tom, please,
reading </code> http://www.odtug.com/2000papers/cassidy.pdf
I found how to create a ddl trigger 

1)I was searching about more information in DBMS_STANDARD standard package and I can't found, I can't believe that.
Do you know where is a detailed explanation of that package (ora9ir2)
DBMS_STANDARD.LOGIN_USER,SYSDATE,
DBMS_STANDARD.DICTIONARY_OBJ_NAME,
DBMS_STANDARD.dictionary_obj_type

I searched
http://www.google.com/search?q=DBMS_STANDARD.DICTIONARY_OBJ_NAME&ie=UTF-8&oe=UTF-8&hl=es&lr= <code>
and it seems this is the only one paper around the world that uses this

2) How can I get the session is to link in the database trigger
CREATE OR REPLACE TRIGGER SYS.TGR_CREATE
AFTER
CREATE
ON DATABASE
BEGIN
END;
to the session to get the machine name, os user, etc.
3) Why when I create an alter trigger and a create trigger only one of them works, I suppose is a bug, or this always work in that way and there is a trick.
I tried several times
creating object
altering object
dropping object

And I can't get alter and create works at the same time.
CREATE OR REPLACE TRIGGER sys.tgr_drop
AFTER
DROP
ON DATABASE
BEGIN
INSERT INTO SYS.ddls
(dd2_user, dd2_time, dd2_objeto, dd2_tipo)
VALUES(
'D-'||DBMS_STANDARD.LOGIN_USER,SYSDATE,
DBMS_STANDARD.DICTIONARY_OBJ_NAME,
DBMS_STANDARD.dictionary_obj_type
);
END;
/
CREATE OR REPLACE TRIGGER sys.tgr_create
AFTER
CREATE
ON DATABASE
BEGIN
INSERT INTO SYS.ddls
(dd2_user, dd2_time, dd2_objeto, dd2_tipo)
VALUES(
'C-'||DBMS_STANDARD.LOGIN_USER,SYSDATE,
DBMS_STANDARD.DICTIONARY_OBJ_NAME,
DBMS_STANDARD.dictionary_obj_type
);
END;
/
CREATE OR REPLACE TRIGGER sys.tgr_alter
AFTER
alter
ON DATABASE
BEGIN
INSERT INTO SYS.ddls
(dd2_user, dd2_time, dd2_objeto, dd2_tipo)
VALUES(
'A-'||DBMS_STANDARD.LOGIN_USER,SYSDATE,
DBMS_STANDARD.DICTIONARY_OBJ_NAME,
DBMS_STANDARD.dictionary_obj_type
);
END;
/


Tom Kyte
May 04, 2004 - 1:37 pm UTC

1) </code> http://docs.oracle.com/docs/cd/B10501_01/appdev.920/a96590/adg14evt.htm#1000872 <code>

no need to use the undocumented package dbms_standard. there are functions to get that stuff.

2) to get the current session --

a) get your DBA to log in as sysdba and grant you select on v_$session and v_$mystat -- and

select * from v$session where sid = ( select sid from v$mystat where rownum = 1)

also see the sys_context function (documented, sql ref), it has tons of capabilities.


3) do NOT ever create things "as sys" unless told to by the documentation or support. SYS is "oracle's" account. Just do use it.


Not sure what you mean by "couldn't get it to work", define that.

A reader, May 04, 2004 - 2:06 pm UTC

Thanks Tom

I did them in this way, any comment (except the use of sys account I'm using only to test in test database)
Now I changed the trigger, I couldn't reproduce the problem with alter and create trigger, now is working fine, if there was some problem now is fixed :).

CREATE OR REPLACE TRIGGER sys.tgr_ALTER
AFTER
ALTER
ON DATABASE
DECLARE
csql_text ora_name_list_t;
n NUMBER;
cSQL CLOB;
var_user varchar2(30);
var_osuser varchar2(30);
var_machine varchar2(64);
var_process varchar2(09);
var_program varchar2(48);
var_sqltext varchar2(1000);
BEGIN
select s.username, s.osuser, s.machine, s.program
into var_user, var_osuser, var_machine, var_program
from sys.v_$session s
,sys.v_$sqlarea t
where s.audsid = userenv('sessionid')
and s.prev_sql_addr = t.address(+)
and s.prev_hash_value = t.hash_value(+)
and username is not null;

n:= ora_sql_txt(csql_text);
FOR I IN 1..N LOOP
cSQL:=cSQL||csql_text(i);
END LOOP;



INSERT INTO SYS.ddls
(dd2_user, dd2_time, dd2_objeto, dd2_tipo,DD2_SQL,
DD2_OSUSER , DD2_MACHINE , DD2_OPROGRAM
)
VALUES(
'A-'||DBMS_STANDARD.LOGIN_USER,SYSDATE,
DBMS_STANDARD.DICTIONARY_OBJ_NAME,
DBMS_STANDARD.dictionary_obj_type,cSQL,
var_osuser, var_machine, var_program
);
END;
/

CREATE OR REPLACE TRIGGER sys.tgr_create
AFTER
CREATE
ON DATABASE
DECLARE
csql_text ora_name_list_t;
n NUMBER;
cSQL CLOB;
var_user varchar2(30);
var_osuser varchar2(30);
var_machine varchar2(64);
var_process varchar2(09);
var_program varchar2(48);
var_sqltext varchar2(1000);
BEGIN
select s.username, s.osuser, s.machine, s.program
into var_user, var_osuser, var_machine, var_program
from sys.v_$session s
,sys.v_$sqlarea t
where s.audsid = userenv('sessionid')
and s.prev_sql_addr = t.address(+)
and s.prev_hash_value = t.hash_value(+)
and username is not null;

n:= ora_sql_txt(csql_text);
FOR I IN 1..N LOOP
cSQL:=cSQL||csql_text(i);
END LOOP;



INSERT INTO SYS.ddls
(dd2_user, dd2_time, dd2_objeto, dd2_tipo,DD2_SQL,
DD2_OSUSER , DD2_MACHINE , DD2_OPROGRAM
)
VALUES(
'C-'||DBMS_STANDARD.LOGIN_USER,SYSDATE,
DBMS_STANDARD.DICTIONARY_OBJ_NAME,
DBMS_STANDARD.dictionary_obj_type,cSQL,
var_osuser, var_machine, var_program
);
END;
/

CREATE OR REPLACE TRIGGER sys.tgr_drop
AFTER
DROP
ON DATABASE
DECLARE
csql_text ora_name_list_t;
n NUMBER;
cSQL CLOB;
var_user varchar2(30);
var_osuser varchar2(30);
var_machine varchar2(64);
var_process varchar2(09);
var_program varchar2(48);
var_sqltext varchar2(1000);
BEGIN
select s.username, s.osuser, s.machine, s.program
into var_user, var_osuser, var_machine, var_program
from sys.v_$session s
,sys.v_$sqlarea t
where s.audsid = userenv('sessionid')
and s.prev_sql_addr = t.address(+)
and s.prev_hash_value = t.hash_value(+)
and username is not null;

n:= ora_sql_txt(csql_text);
FOR I IN 1..N LOOP
cSQL:=cSQL||csql_text(i);
END LOOP;



INSERT INTO SYS.ddls
(dd2_user, dd2_time, dd2_objeto, dd2_tipo,DD2_SQL,
DD2_OSUSER , DD2_MACHINE , DD2_OPROGRAM
)
VALUES(
'D-'||DBMS_STANDARD.LOGIN_USER,SYSDATE,
DBMS_STANDARD.DICTIONARY_OBJ_NAME,
DBMS_STANDARD.dictionary_obj_type,cSQL,
var_osuser, var_machine, var_program
);
END;
/





Tom Kyte
May 04, 2004 - 3:24 pm UTC

stop using dbms_standard
start using the documented functions.

use v$session and v$sqlarea, not v_

you have a select into with out an exception block for NO_DATA_FOUND

You could skip the select into alltogether and


insert into ddls
select <functions>, <columns> from v$session, v$sqlarea;


and only have procedural code to turn the sql text array into a string.


A reader, May 04, 2004 - 3:45 pm UTC

Thanks Tom, could you fix one trigger please,if I'm not abusing from you. please

Tom Kyte
May 04, 2004 - 7:30 pm UTC


CREATE OR REPLACE TRIGGER tgr_ALTER
AFTER ALTER ON DATABASE
DECLARE
csql_text ora_name_list_t;
n NUMBER;
cSQL CLOB;
BEGIN
n:= ora_sql_txt(csql_text);
FOR I IN 1..N LOOP
cSQL:=cSQL||csql_text(i);
END LOOP;

INSERT INTO ddls
(dd2_user, dd2_time, dd2_objeto, dd2_tipo,DD2_SQL,
DD2_OSUSER , DD2_MACHINE , DD2_OPROGRAM)

select sys_context( 'userenv', 'current_user' ),
sysdate,
ora_dict_obj_name,
ora_dict_obj_type,
cSQL,
sys_context( 'userenv', 'external_name' ),
s.machine,
s.program
from v$session s
where sid = ( select sid from v$mystat where rownum=1 );
END;

What is the difference

Reader, May 05, 2004 - 1:22 am UTC

Hi Tom,
You have said,
<quote>
stop using dbms_standard
start using the documented functions.
<quote>

What is the difference?
Why should not we use?
Is there any specific reason to use?

Tom Kyte
May 05, 2004 - 7:43 am UTC

because

one is not documented, hence not understood, not supported, not to be used

and the other

is documented
is understood
is supported
is to be used......

A reader, May 05, 2004 - 9:18 am UTC

Really Thanks Tom

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library