sql >> Databasteknik >  >> RDS >> Oracle

Beräkna ålder från födelsedag med oracle plsql trigger och infoga åldern i tabellen

snälla hjälp...jag behöver verkligen det här...

Nej, det gör du inte. Jag är inte säker på att du kommer att vara uppmärksam; och det finns ingen anledning till varför du skulle göra det :-) men:

Lagra inte ålder i din databas. Du har helt garanterat fel ibland. Åldern förändras varje år för varje person, men den ändras varje dag för vissa människor. Detta innebär i sin tur att du behöver ett batchjobb att köra varje dag och uppdatera ålder. Om detta misslyckas eller inte är extremt strikt och blir körd två gånger, har du problem.

Du bör alltid beräkna åldern när du behöver det. Det är en ganska enkel fråga och sparar dig mycket smärta på längre sikt.

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

Jag har satt upp en liten SQL Fiddle för att demonstrera

Nu för att faktiskt svara på din fråga

denna procedur fungerar bra men för bara en rad,,,men för alla rader behöver trigger men om jag anropar den från en trigger så uppstår felet...

Du nämner inte felet, vänligen gör detta i framtiden eftersom det är till stor hjälp, men jag misstänker att du får

ORA-04091:tabellen string.string muterar, trigger/funktion kanske inte ser den

Detta beror på att din procedur frågar efter tabellen som uppdateras. Oracle tillåter inte detta för att upprätthålla en läskonsekvent bild av data. Sättet att undvika detta är att inte fråga i tabellen, vilket du inte behöver göra. Ändra din procedur till en funktion som returnerar korrekt resultat givet ett födelsedatum:

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;

Lägg igen märke till att jag använder months_between() fungerar då inte alla år har 365 dagar.

I din trigger tilldelar du sedan värdet direkt till kolumnen.

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

:new.<column> syntax är en referens till <column> som håller på att uppdateras. I det här fallet :new.age är det faktiska värdet som kommer att anges i tabellen.

Detta innebär att din tabell kommer att uppdateras automatiskt, vilket är poängen med en DML-utlösare.

Som du kan se finns det ingen mening med funktionen alls; din trigger kan bli

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; 

Men med det sagt, om du ska använda den här funktionen någon annanstans i databasen, håll den separat. Det är bra att ha kod som används på flera ställen i en funktion som denna så att den alltid används på samma sätt. Det säkerställer också att när någon beräknar ålder så gör de det ordentligt.

Som en liten bit bort är du säker på att du vill tillåta människor att vara 9 999 år gamla? Eller 0,00000000001998 (bevis)? Numerisk precision baseras på antalet signifikanta siffror; detta (enligt Oracle) är ej noll endast nummer. Du kan lätt bli fångad av detta. Poängen med en databas är att begränsa de möjliga indatavärdena till endast de som är giltiga. Jag skulle allvarligt överväga att deklarera din ålderskolumn som number(3,0) för att säkerställa att endast "möjliga" värden ingår.



  1. Uppdatera ett kolumnvärde och ersätt en del av en sträng

  2. Standardisera PostgreSQL-säkerhet i flera molnmiljöer

  3. En recension av de nya analytiska fönsterfunktionerna i MySQL 8.0

  4. Villkorlig aggregeringsprestanda