简体   繁体   中英

How to properly call a function with date parameter?

I had to create a function that computes how many people are born from the given date as a parameter.

I have a table named Person with date of birth written as "YY/MM/DD".

The function is as follows :

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;

And i tried to run this function :

SET SERVEROUTPUT ON

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

but it doesn't work. I get a message that number of parameters is not valid or that tha day/month is invalid.

Your function takes a date parameter, but you are passing a string; and within the function you're converting an argument that is already a date into a date, which doesn't make much sense. Both are relying on your session NLS_DATE_FORMAT to do do implicit conversions. Inside the function you're effectively doing:

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

while in the call you're doing:

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

If you're lucky your session will be set up right, but here you're relying on conflicting formats, so one or the other will fail or get an unexpected answer. You shouldn't rely on NLS settings, and you shouldn't convert a date to a string and back.

You want something more like:

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;

Although you may actually want >= p_date . And then call it with an explicit date, such as:

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

(note the four-digit year; don't use two-digit years, even with the RR format model element), or an ANSI date literal:

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

I have a table named Person with date of birth written as "YY/MM/DD"

If your column has data type DATE then it has no intrinsic format. If you query the table and see date values formatted like that then your NLS_DATE_FORMAT is YY/MM/DD or maybe RR/MM/DD; or a client setting is formatting the date implicitly. It isn't stored like that and changing the client/session settings will change how it's displayed. It's possible you actually have it stored as a formatted string, but that would be a really bad idea, and your question implies it is actually a date.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM