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.
trunc(sysdate - rownum) AS birthDate,
trunc(sysdate) AS todaysDate,
trunc((months_between(sysdate, (sysdate - rownum)))/12) AS age
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.