Oracle
 sql >> Base de données >  >> RDS >> Oracle

Calcul de l'âge à partir de l'anniversaire avec le déclencheur oracle plsql et insertion de l'âge dans le tableau

aidez-moi s'il vous plaît... j'en ai vraiment besoin...

Non, vous ne le faites pas. Je ne suis pas sûr que vous ferez attention; et il n'y a aucune raison de le faire :-) mais :

Ne stockez pas l'âge dans votre base de données. Vous êtes absolument assuré de vous tromper de temps en temps. L'âge change chaque année pour chaque personne, cependant, il change tous les jours pour certaines personnes. Cela signifie à son tour que vous avez besoin d'un travail par lots pour exécuter tous les jours et mettre à jour l'âge. Si cela échoue, ou n'est pas extrêmement strict et se fait exécuter deux fois, vous avez des ennuis.

Vous devriez toujours calculer l'âge auquel vous en avez besoin. Il s'agit d'une requête assez simple qui vous évite bien des soucis à long terme.

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

J'ai mis en place un petit SQL Fiddle pour démontrer

Maintenant, pour répondre réellement à votre question

cette procédure fonctionne bien mais pour une seule ligne, mais pour toutes les lignes, j'ai besoin d'un déclencheur mais si je l'appelle à partir d'un déclencheur, l'erreur se produit ...

Vous ne mentionnez pas l'erreur, veuillez le faire à l'avenir car c'est très utile, mais je soupçonne que vous obtenez

ORA-04091 :la table string.string est en train de muter, le déclencheur/la fonction peut ne pas le voir

En effet, votre procédure interroge la table en cours de mise à jour. Oracle ne le permet pas afin de maintenir une vue cohérente en lecture des données. Le moyen d'éviter cela est de ne pas interroger la table, ce que vous n'avez pas besoin de faire. Remplacez votre procédure par une fonction qui renvoie le résultat correct compte tenu d'une date de naissance :

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;

Remarquez encore une fois que j'utilise le months_between() fonctionner car toutes les années n'ont pas 365 jours.

Dans votre déclencheur, vous affectez ensuite la valeur directement à la colonne.

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

Le :new.<column> la syntaxe est une référence au <column> qui est en cours de mise à jour. Dans ce cas :new.age est la valeur réelle qui va être mise dans le tableau.

Cela signifie que votre tableau sera automatiquement mis à jour, ce qui est le but d'un déclencheur DML.

Comme vous pouvez le voir, la fonction n'a que peu d'intérêt; votre déclencheur peut devenir

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; 

Cependant, cela dit, si vous comptez utiliser cette fonction ailleurs dans la base de données, gardez-la séparée. Il est recommandé de conserver le code utilisé à plusieurs endroits dans une fonction comme celle-ci afin qu'il soit toujours utilisé de la même manière. Cela garantit également que chaque fois que quelqu'un calcule l'âge, il le fera correctement.

En aparté, êtes-vous sûr de vouloir autoriser les gens à avoir 9 999 ans ? Ou 0.000000000001998 (preuve) ? La précision numérique est basée sur le nombre de significatif chiffres ; ceci (selon Oracle) est non nul chiffres uniquement. Vous pouvez facilement être pris au dépourvu. Le but d'une base de données est de limiter les valeurs d'entrée possibles à celles qui sont valides. J'envisagerais sérieusement de déclarer votre colonne d'âge sous la forme number(3,0) pour s'assurer que seules les valeurs "possibles" sont incluses.