我必须创建一个函数来计算从给定日期出生的人数作为参数。
我有一张名为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;
但它不起作用。我收到一条消息,指出参数数量无效或日/月无效。
答案 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;或客户端设置隐式格式化日期。它不是那样存储的,更改客户端/会话设置将改变它的显示方式。 可能你实际上将它存储为格式化的字符串,但这是一个非常糟糕的主意,而你的问题暗示它实际上是一个日期。