Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> Re: trigger on alter table to re-create archiving trigger. (advanced) (RP)

Re: trigger on alter table to re-create archiving trigger. (advanced) (RP)

From: Marc Blum <marc_at_marcblum.de>
Date: Wed, 28 Aug 2002 21:51:20 +0200
Message-ID: <22aqmu87ck4em322fcgo79sck6nrmt9bl7@4ax.com>


On 26 Aug 2002 08:15:45 -0700, jochen.vandenbossche_at_proximus.net (Jochen Van den Bossche) wrote:

>I have a database with lots of tables (313), some tables have many
>columns (332). and, yes, this if fully normalised...
>
>I recently developped an archiving system with a shadow table for
>every table where triggers record any DML.
>
>Fortunatly I first developped a procedure that generates the SQL
>necessary to create the archive tables and the triggers. A problem was
>that to generate the create table and the trigger for this 300+ column
>table, I had to use a CLOB as destination for the SQL code.
>
>This system worked perfectly to create the tables and trigger, but now
>(as foreseen) the next problem arises: The tables are altered now and
>then...
>This forces us to also alter the shadow tables and the triggers.
>
>Altering the shadow tables is easy: it is just a copy paste of the
>alter table statement for the base table with the addition of a few
>columns specic to the archive (always the same).
>
>More difficult is altering the triggers. Currently the developpers
>need to use the generation procedure, get the new trigger from that
>table and then execute it...
>
>I need something like an "on alter table" trigger to regenerate the
>trigger code. And then "execute immediate" the generated code.
>
>Is something like that possible?
>
>Can I put a trigger on user_tab_columns? I think I'll run in to the
>fact that a normal (non system) trigger can not perform DDL. to quote
>the manual: [quote] DDL statements are not allowed in the body of a
>trigger. Also, no transaction control statements are allowed in a
>trigger. ROLLBACK, COMMIT, and SAVEPOINT cannot be used. For system
>triggers, {CREATE/ALTER/DROP} TABLE statements and ALTER...COMPILE are
>allowed.[/quote]
>
>So then I'll have to use an AFTER ALTER (schema) trigger.
>Does anyone have any examples of this kind of triggers? What values
>can I expect in the associated "Atteribute functions"
>(ora_dict_obj_type, ora_dict_obj_name, ora_is_alter_column,
>ora_is_drop_column, ...)?
>
>Does execute immediate work with CLOBs (or statemnts with more than
>4000 characters) or should I look into dbms_sql? Or can I use something
>like varchar(30000) since it is inside a PL/SQL block?
>
>Any help greatly appreciated.
>jochen.

How about a schema level trigger, which traps DDL. There's one problem with that. You can't execute DDL inside a Trigger. Possible solution: Generate the code to modify the arc table and recreate the trigger and put it into a job via DBMS_JOB, to be executed in say 1 minute. So with a bit delay, you get the task done.

Here's an example for trapping DDL:

conn SYSTEM/manager_at_demo

DROP USER marc CASCADE
/
CREATE USER marc
IDENTIFIED BY marc
DEFAULT TABLESPACE ts_data
QUOTA UNLIMITED ON ts_data
/
GRANT CREATE SESSION TO marc
/
GRANT ALTER SESSION TO marc
/
GRANT CREATE TABLE TO marc
/
GRANT CREATE TRIGGER TO marc
/
GRANT CREATE PROCEDURE TO marc
/
conn marc/marc_at_demo
CREATE TABLE t_ddl_log
(obj_name VARCHAR2(30),
 obj_type VARCHAR2(30),
 action VARCHAR2(1),
 zeitpunkt DATE)
/
CREATE OR REPLACE TRIGGER log_create

   AFTER CREATE ON marc.SCHEMA
DECLARE

   l_obj VARCHAR2(30);      
   l_type VARCHAR2(30);      
BEGIN                 

   l_obj := dictionary_obj_name;
   l_type := dictionary_obj_type;
   --
   INSERT INTO t_ddl_log
   VALUES
   (l_obj,
    l_type,
    'C',
    SYSDATE);
END;
/
CREATE OR REPLACE TRIGGER log_drop

   AFTER DROP ON marc.SCHEMA
DECLARE

   l_obj VARCHAR2(30);      
   l_type VARCHAR2(30);      
BEGIN                 

   l_obj := dictionary_obj_name;
   l_type := dictionary_obj_type;
   --
   INSERT INTO t_ddl_log
   VALUES
   (l_obj,
    l_type,
    'D',
    SYSDATE);
END;
/
SELECT * FROM t_ddl_log
/
CREATE OR REPLACE PACKAGE mrc$p_test
AS
l_var VARCHAR2(100);
END mrc$p_test;
/
SELECT * FROM t_ddl_log
/
CREATE OR REPLACE PACKAGE mrc$p_test
AS
l_var VARCHAR2(100);
l_var2 VARCHAR2(100);
END mrc$p_test;
/
SELECT * FROM t_ddl_log
/
CREATE OR REPLACE PACKAGE BODY mrc$p_test AS
BEGIN
   NULL;
END mrc$p_test;
/
SELECT * FROM t_ddl_log
/
DROP PACKAGE mrc$p_test
/
SELECT * FROM t_ddl_log
/

Marc Blum
mailto:marc_at_marcblum.de
http://www.marcblum.de Received on Wed Aug 28 2002 - 14:51:20 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US