Oracle
 sql >> Database >  >> RDS >> Oracle

Calcolare l'età dal compleanno con oracle plsql trigger e inserire l'età nella tabella

per favore aiutatemi... ne ho davvero bisogno...

No, non lo fai. Non sono sicuro che presterai attenzione; e non c'è motivo per cui dovresti :-) ma:

Non memorizzare l'età nel database. Hai assolutamente la certezza di sbagliare di tanto in tanto. L'età cambia ogni anno per ogni persona, tuttavia cambia ogni giorno per alcune persone. Ciò a sua volta significa che è necessario un processo batch da eseguire ogni giorno e aggiornare l'età. Se fallisce o non è estremamente severo e viene eseguito due volte, sei nei guai.

Dovresti sempre calcola l'età quando ne hai bisogno. È una query abbastanza semplice e ti fa risparmiare molto dolore a lungo termine.

select floor(months_between(sysdate,<dob>)/12) from dual

Ho impostato un piccolo SQL Fiddle per dimostrarlo

Ora, per rispondere effettivamente alla tua domanda

questa procedura funziona bene ma solo per una riga,,, ma per tutte le righe ho bisogno di un trigger ma se lo chiamo da un trigger allora si verifica l'errore...

Non menzioni l'errore, fallo in futuro perché è molto utile, ma sospetto che tu stia ricevendo

ORA-04091:la tabella string.string sta mutando, il trigger/la funzione potrebbe non vederlo

Questo perché la tua procedura sta interrogando la tabella che si sta aggiornando. Oracle non lo consente al fine di mantenere una visualizzazione coerente in lettura dei dati. Il modo per evitarlo è non interrogare la tabella, cosa che non è necessario fare. Cambia la tua procedura in una funzione che restituisce il risultato corretto data una data di nascita:

function get_age (pDOB date) return number is
   /* Return the the number of full years between 
      the date given and sysdate.
      */    
begin    
   return floor(months_between(sysdate,pDOB)/12);    
end;

Nota ancora una volta che sto usando months_between() funzione in quanto non tutti gli anni hanno 365 giorni.

Nel tuo trigger assegni quindi il valore direttamente alla colonna.

CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
   :new.age := get_age(:new.dob);
END;

Il :new.<column> la sintassi è un riferimento a <column> che è in fase di aggiornamento. In questo caso :new.age è il valore effettivo che verrà inserito nella tabella.

Ciò significa che la tua tabella verrà aggiornata automaticamente, che è il punto di un trigger DML.

Come puoi vedere, la funzione ha poco senso; il tuo trigger può diventare

CREATE OR REPLACE TRIGGER agec before INSERT OR UPDATE ON dates
FOR EACH ROW
BEGIN
   :new.age := floor(months_between(sysdate,:new,DOB)/12);
END; 

Tuttavia, detto questo, se hai intenzione di utilizzare questa funzione altrove nel database, tienila separata. È buona norma mantenere il codice utilizzato in più posizioni in una funzione come questa in modo che venga sempre utilizzato allo stesso modo. Garantisce inoltre che ogni volta che qualcuno calcola l'età lo farà correttamente.

Per inciso, sei sicuro di voler permettere alle persone di avere 9.999 anni? O 0,000000000001998 (prova)? La precisione numerica si basa sul numero di significativi cifre; questo (secondo Oracle) è diverso da zero solo numeri. Puoi facilmente essere catturato da questo. Lo scopo di un database è limitare i possibili valori di input solo a quelli validi. Prenderei seriamente in considerazione la possibilità di dichiarare la colonna dell'età come number(3,0) per garantire che siano inclusi solo i valori "possibili".