如何从存储的字符串日期(PL / SQL)打印十进制数

时间:2015-05-21 13:28:27

标签: sql oracle plsql

尝试解决一项任务,其中包含一个由汽车所有者组成的表格。我应该写一个匿名的PLSQL语句,我应该打印名字,姓氏和所有者的年龄,如果他们的dob是'19801109'它应该将它转换为他们的年龄数字,一个小数,如' 34,4岁'。怎么做? (你可以想象这是非常新的)。 这是我的代码,没有任何转换/计算功能:

declare
cursor c_owners is select initcap(fname), initcap(lname), dob
                from car_owner;
v_dob car_owner.pnr%type;
v_fnamn car_owner.fname%type;
v_enamn car_owner.lname%type;
begin 
  if not c_owners%isopen then
  open c_owner;
  end if;
     loop
     fetch c_owner
     into v_fname, v_lname, v_dob;
     exit when c_owners%notfound;
     dbms_output.put_line(v_fname||', '||v_lname||', '||v_dob||'year.');
     end loop;

close c_owners;
end;
/
如果有人可以提供帮助,那会很棒。已经坚持了一段时间了。我知道我可以使用更好的写作方式来获得更少的代码但是首先要学习基础知识:) 结果应如下所示:

John,Johnson,34岁。

当我问他的朋友时他是这样做的:

begin 
for rec in select fname, lname, round (months_between(sysdate,  to_Date('19'|| 
SUBSTR(dob,0), INSTR(dob, '-')-1)'YYMMDD')) as age 
from car_owner; 
loop dbms_output.put_line(initcat(rec.fname) || ', '|| initcap(rec.lname) ||' , '|| rec.age||' age'; 
end loop; 
end;
/

但那不起作用(无论我怎么做都令人烦恼的右括号错误),我完全不了解它,但也许它可以帮助你看看它应该是什么样子?表格中大约十行,输出应根据其dob打印每个年龄。

2 个答案:

答案 0 :(得分:0)

你需要一些关于生日的数学。将其转换为日期,从当前日期减去它除以365年。然后使用to_char()格式化为1十进制:

SQL> with tbl(fname, lname, DOB) as
  2  ( select 'John', 'Johnson', '19081109' from dual
  3  )
  4  select fname, lname, to_char((sysdate - to_date('19801109','yyyymmdd'))/365, '99.9') age from tbl;

FNAM LNAME   AGE
---- ------- -----
John Johnson  34.6

SQL>

所以对你的例子来说:

select initcap(fname), initcap(lname), to_char((sysdate - to_date(dob,'yyyymmdd'))/365, '99.9') || ' years old' age
                from car_owner;

答案 1 :(得分:0)

关于在C#中获得精确年龄,这是一个很好的答案: Age in years with decimal precision given a datetime

转换为PL / SQL:

declare
  v_dob varchar(8) := '19801109';
  v_dob_as_date date := to_date(v_dob,'yyyymmdd');
  v_current_date date := sysdate;
  v_years integer;
  v_last_birthday date;
  v_next_birthday date;
begin
    v_years := extract(year from v_current_date) - extract(year from v_dob_as_date);
    v_last_birthday := ADD_MONTHS(v_dob_as_date, 12 * v_years);
    if v_last_birthday > v_current_date then
      v_years := v_years -1;
      v_last_birthday := ADD_MONTHS(v_dob_as_date, 12 * v_years);
    end if;
    v_next_birthday := ADD_MONTHS(v_last_birthday, 12);
    dbms_output.put_line('Years old (whole number): ' || v_years);
    dbms_output.put_line('Last birthday: ' ||  v_last_birthday);
    dbms_output.put_line('Next birthday: ' ||  v_next_birthday);
    dbms_output.put_line('Days between last and next birthdays: ' ||  (v_next_birthday - v_last_birthday));
    dbms_output.put_line('Days since last birthday: ' ||  (v_current_date - v_last_birthday));
    dbms_output.put_line('Exact age: ' || round(v_years + ( (v_current_date - v_last_birthday) / (v_next_birthday - v_last_birthday)),1));
end;

结果(SYSDATE为21-MAY-15 10:45:11 AM)为34.5。用更简单的程序得到同样的东西:

declare
  v_dob varchar(8) := '19801109';
  v_dob_as_date date := to_date(v_dob,'yyyymmdd');
begin
  dbms_output.put_line('Age: ' || round(months_between(sysdate,to_date('19801109','yyyymmdd'))/12,1));
end;

如果舍入到小数点后5位,则结果会有所不同。第一种方法产生34.52999,第二种方法产生34.53346。