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

如何从存储的字符串日期(PL/SQL)打印十进制数,sql,oracle,plsql,Sql,Oracle,Plsql,试图解决一个任务,其中我有一个由车主组成的表格。我应该写一个匿名的PLSQL语句,在这里我应该打印名字、姓氏和所有者的年龄,比如如果他们的dob是'19801109',它应该将其转换为一个数字中的年龄,带一个小数点,比如'34,4岁'。怎么做?(你可以想象,这是一个非常新的概念)。 这是我的代码,没有任何转换/计算功能: declare cursor c_owners is select initcap(fname), initcap(lname), dob fr

试图解决一个任务,其中我有一个由车主组成的表格。我应该写一个匿名的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;
/
如果有人能帮忙,那就太棒了。我已经被这个问题困扰了一段时间了。我知道我可以用更好的方式编写更少的代码,但首先要努力学习基础知识:) 结果应该如下所示:

约翰,约翰逊,34,4岁

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

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

但这并没有起作用(不管我怎么做,都会出现恼人的右括号错误),我也没有完全理解它,但也许它可以帮助您看到它应该是什么样子?表中大约有十行,输出应该根据每个人的出生日期打印他们的年龄。

你只需要计算一下生日。将其转换为一个日期,从当前日期中减去,然后除以365年。然后使用to_char()将格式设置为1位小数:

以你为例:

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

这里有一个很好的答案,关于C#的精确年龄:

转换为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;
结果(系统日期为2015年5月21日上午10:45:11)为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。

Lookup Datediff:@ChristianBarron:PL/SQL(=Oracle)中没有Datediff,我错过了PL/SQL标记。我还以为甲骨文会,但也许我被这个误导了:对不起,你是怎么得到34.4的?我最接近的是34岁。53@ChristianBarron:在Oracle(或一般的标准SQL)中,您只需编写
date\u one-date\u two
某个日期-间隔“5”天
-不需要这样的函数。有些年份的天数超过365天。请尝试在(date v\u dob,sysdate)/12这两个月之间写几个月,这是提出闰年的好方法,等等。取决于OP需要的准确度?我怀疑这是一个粗略的估计。这是一个很好的例子,说明了为什么在定义需求或确保获得特定需求时必须非常具体!开发人员可能会错误地解释小于特定值的内容。
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;