There are some complicated results that come up when a Google search is done for this, but really it’s quite simple with the function months_between.
Usage: trunc((months_between(sysdate, (DOB)))/12) as age
where DOB is the birth date and sysdate is today’s date.
select trunc(sysdate - rownum) as birthDate, trunc(sysdate) as todaysDate, trunc((months_between(sysdate, (sysdate - rownum)))/12) as age from all_tab_cols
where (sysdate – rownum) is the birth date and all_tab_cols is some table with a lot of rows in it. Scrolling through the results of the above query you can see that the age is correct to the day, every day.