如何使用日期参数正确调用函数?

时间:2017-01-28 18:12:17

标签: sql oracle date

我必须创建一个函数来计算从给定日期出生的人数作为参数。

我有一张名为Person的表,出生日期写为" YY / MM / DD"。

功能如下:

create or replace function persons_count(p_date date) RETURN NUMBER IS cnt NUMBER; 
BEGIN`
  SELECT COUNT(*) INTO cnt FROM person
  WHERE date_of_birth > To_Date(p_date,'dd.mm.yyyy'); 
  RETURN cnt;
END;

我试图运行这个功能:

SET SERVEROUTPUT ON

DECLARE
  num NUMBER;
BEGIN
  num := persons_count('82/11/01');
  dbms_output.put_line(num);
END;

但它不起作用。我收到一条消息,指出参数数量无效或日/月无效。

1 个答案:

答案 0 :(得分:2)

您的函数采用日期参数,但您传递的是字符串;在函数中,您将一个已经是日期的参数转换为日期,这没有多大意义。两者都依赖于您的会话NLS_DATE_FORMAT来执行隐式转换。在你正在做的功能里面:

WHERE date_of_birth > To_Date(to_char(p_date, NLS_DATE_FORMAT),'dd.mm.yyyy'); 

在你正在做的电话中:

persons_count(to_date('82/11/01', NLS_DATE_FORMAT));

如果你很幸运,你的会话将被设置正确,但在这里你依赖于相互冲突的格式,因此一个或另一个会失败或得到一个意想不到的答案。您不应该依赖NLS设置,也不应该将日期转换为字符串并返回。

你想要更像的东西:

create or replace function persons_count(p_date date)
RETURN NUMBER IS
  cnt NUMBER; 
BEGIN
  SELECT COUNT(*) INTO cnt
  FROM person
  WHERE date_of_birth > p_date;
  RETURN cnt;
END;

虽然您可能真的想要>= p_date。然后使用明确的日期调用它,例如:

num := persons_count(to_date('1982/11/01', 'YYYY/MM/DD));

(注意四位数年份;不要使用两位数年份,即使使用RR格式模型元素),也不要使用ANSI日期文字:

num := persons_count(DATE '1982-11-01');
  

我有一张名为Person的表,其出生日期写为“YY / MM / DD”

如果您的列的数据类型为DATE,则它没有内在格式。如果查询表并查看格式相似的日期值,则NLS_DATE_FORMAT为YY / MM / DD或RR / MM / DD;或客户端设置隐式格式化日期。它不是那样存储的,更改客户端/会话设置将改变它的显示方式。 可能你实际上将它存储为格式化的字符串,但这是一个非常糟糕的主意,而你的问题暗示它实际上是一个日期。