Newsgroup: it.comp.software.database
Titolo: Oracle e problema delle mutating Table

Allora ho una tabella nick (ID, tipo, nick) ogni id può essere
registrato con più di un nick, ma solo un nick per ogni ID può essere
di tipo principale, tutti gli altri saranno Secondari.
Ho fatto un trigger, che mi funziona quando si tratta di controllare
l'insert ma mi và in mutating table per l'update.
Questi sono gli errori:
error ORA-04091: La tabella MARIANO.NICK è in fase di modifica, il
trigger/funzione non può leggerla ORA-06512: a "MARIANO.NO_REP", line
7 ORA-04088: errore durante esecuzione del trigger 'MARIANO.NO_REP'
Questo è il trigger:
CREATE OR REPLACE TRIGGER NO_REP
   before insert or update of tipo on NICK
   for each row
declare
   num NUMBER(5);
   no_insert EXCEPTION;
   no_update EXCEPTION;
begin
IF :new.tipo = 'Principale' THEN
  SELECT COUNT(*) into num
  FROM nick
  WHERE ID = :
new.id
 AND tipo LIKE 'Principale';
  IF num >= 1 THEN
     IF INSERTING THEN
        RAISE no_insert;
     ELSE
        RAISE no_update;
     END IF;
  END IF;
END IF;
  EXCEPTION
     WHEN no_insert THEN
       RAISE_APPLICATION_ERROR (
         -20002, 'INSERIMENTO ERRATO: c già un nick di tipo
PRINCIPALE!!!');
     WHEN no_update THEN
       RAISE_APPLICATION_ERROR (
         -20001, 'AGGIORNAMENTO ERRATO: c già un nick di tipo
PRINCIPALE!!!'); 
END;

 l'insert ma mi và in mutating table per l'update.
Mi pare che di solito un errore di mutating table si ha quando si cerca
di utilizzare un trigger per un controllo di integrità, invece di
lasciarlo alla corretta progettazione delle relazioni.
Nel tuo caso, se non puoi cambiare lo schema, potrebbe servire un indice
univoco/constraint del tipo:
SQL> create unique index nick_check on nick (decode(tipo = 'principale',
id, null), decode(tipo = 'principale', tipo, null));
Scusa non ho una istanza usabile sotto mano, quindi non posso
controllare la sintassi.
Bye
-- 
Rudy
blog: 
http://rdbland.blogspot.com/
e-mail a 
email.it

 controllare la sintassi.
Vabbè, io e il mio decode personalizzato...
Devi avere il query rewrite privilege.
SQL> create unique index idtipo_check on idtipo (decode(tipo, 'princ',
id, null), decode(tipo, 'princ', tipo, null));
Index created.
SQL> insert into idtipo values (1, 'princ', 'nick1');
1 row created.
SQL> insert into idtipo values (2, 'altro', 'nick2');
1 row created.
SQL> insert into idtipo values (3, 'princ', 'nick3');
1 row created.
SQL> insert into idtipo values (1, 'princ', 'nick4');
insert into idtipo values (1, 'princ', 'nick4')
*
ERROR at line 1:
ORA-00001: unique constraint (RUDY.IDTIPO_CHECK) violated
SQL> insert into idtipo values (1, 'altro', 'nick5');
1 row created.


Scusa l'ignoranza, ma mi sto avvicinando ad Oracle per la prima volta
per via dell'università. Ma con la tua soluzione evito il trigger?
Rudy ha scritto:


 lasciarlo alla corretta progettazione delle relazioni.
Molto buono; filosoficamente più giusto, e comunque più robusto, l'uso
di constraint dichiarativi invece di trigger per la data integrity.
Non soltanto un trigger richiede un'attenzione maggiore e presenta
varie trappole che l'esperienza dolorosamente insegnerà, ma la DRI
è più robusta e maggiormente comprensibile al dbms.
Uno dei pregi della DRI è che essendo scritta in linguaggio
dichiarativo, è sfruttabile dal dbms per derivarne funzionalità; ad
esempio, query optimizer può sfruttarlo per costruire piani di
esecuzione migliori avendo una conoscenza CERTA di ciò che una colonna
può e non può contenere (senza neppure toccare i dati!).
Per contro, un trigger, essendo codice procedurale, è incomprensibile
(opaco) al dbms, e può solamente mandarlo in esecuzione per recepirne
il risultato.
Promemoria per il nostro studente in erba (in senso non parlamentare):
usare la DRI innanzitutto.
bye