Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Berechnung des Alters aus dem Geburtstag mit dem Oracle-PLSQL-Trigger und Einfügen des Alters in die Tabelle

bitte helft mir... ich brauche das wirklich...

Nein, tust du nicht. Ich bin mir nicht sicher, ob Sie darauf achten werden; und es gibt keinen Grund, warum Sie sollten :-) aber:

Alter nicht in Ihrer Datenbank speichern. Es ist absolut garantiert, dass Sie sich gelegentlich irren. Das Alter ändert sich jedes Jahr für jede Person, jedoch ändert es sich bei manchen Menschen jeden Tag. Dies wiederum bedeutet, dass Sie jeden Tag einen Batch-Job ausführen und das Alter aktualisieren müssen. Wenn dies fehlschlägt oder nicht extrem streng ist und zweimal überfahren wird, sind Sie in Schwierigkeiten.

Sie sollten immer Berechnen Sie das Alter, wenn Sie es brauchen. Es ist eine ziemlich einfache Abfrage und erspart Ihnen auf lange Sicht viel Ärger.

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

Ich habe zur Demonstration eine kleine SQL-Fiddle eingerichtet

Nun zur eigentlichen Beantwortung Ihrer Frage

Dieses Verfahren funktioniert gut, aber nur für eine Zeile, aber für alle Zeilen muss ich triggern, aber wenn ich es von einem Trigger aus aufrufe, tritt der Fehler auf ...

Sie erwähnen den Fehler nicht, tun Sie dies bitte in Zukunft, da es sehr hilfreich ist, aber ich vermute, Sie erhalten

ORA-04091:Tabelle string.string mutiert, Trigger/Funktion sieht sie möglicherweise nicht

Dies liegt daran, dass Ihre Prozedur die zu aktualisierende Tabelle abfragt. Oracle lässt dies nicht zu, um eine lesekonsistente Ansicht der Daten zu erhalten. Die Möglichkeit, dies zu vermeiden, besteht darin, die Tabelle nicht abzufragen, was Sie nicht tun müssen. Ändern Sie Ihre Prozedur in eine Funktion, die bei einem Geburtsdatum das richtige Ergebnis zurückgibt:

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;

Beachten Sie noch einmal, dass ich months_between() verwende funktionieren, da nicht alle Jahre 365 Tage haben.

In Ihrem Trigger weisen Sie den Wert dann direkt der Spalte zu.

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

Der :new.<column> Syntax ist ein Verweis auf <column> das wird aktualisiert. In diesem Fall :new.age ist der tatsächliche Wert, der in die Tabelle eingetragen wird.

Das bedeutet, dass Ihre Tabelle automatisch aktualisiert wird, was der Punkt eines DML-Triggers ist.

Wie Sie sehen können, hat die Funktion überhaupt keinen Sinn; Ihr Auslöser kann

werden
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; 

Wenn Sie diese Funktion jedoch an anderer Stelle in der Datenbank verwenden, halten Sie sie separat. Es empfiehlt sich, Code, der an mehreren Stellen in einer Funktion wie dieser verwendet wird, so aufzubewahren, dass er immer auf die gleiche Weise verwendet wird. Es stellt auch sicher, dass jeder, der das Alter berechnet, es richtig macht.

Sind Sie sicher, dass Sie zulassen wollen, dass Menschen 9.999 Jahre alt werden? Oder 0,000000000001998 (Beweis)? Die numerische Genauigkeit basiert auf der Anzahl der signifikanten Ziffern; diese ist (laut Oracle) nicht Null nur Zahlen. Sie können leicht davon erwischt werden. Der Sinn einer Datenbank besteht darin, die möglichen Eingabewerte auf die gültigen zu beschränken. Ich würde ernsthaft in Betracht ziehen, Ihre Altersspalte als number(3,0) zu deklarieren um sicherzustellen, dass nur "mögliche" Werte enthalten sind.