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;
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;
/
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;
/
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
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?
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