2017-01-28 49 views
1

我不得不創建一個函數來計算從給定日期出生的人數作爲參數。如何正確調用帶日期參數的函數?

我有一張名爲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

如果您正在查找自特定日期以來僱傭了多少人*,您爲什麼要查看他們的DOB? –

+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'); 

我有一個名爲人用寫爲 「YY/MM/DD」

出生日期表如果您的列具有數據類型DATE,那麼它沒有內在格式。如果您查詢表格並查看格式化日期值,那麼您的NLS_DATE_FORMAT爲YY/MM/DD或RR/MM/DD;或者客戶端設置隱式地格式化日期。它不是像那樣存儲的,改變客戶端/會話設置會改變它的顯示方式。這是可能你實際上已經將它存儲爲一個格式化的字符串,但這將是一個非常糟糕的主意,你的問題意味着它實際上是一個日期。

+0

是的,在表格中列的數據類型爲DATE。感謝您的幫助,它現在正常運行:) –