2016-02-18 21 views
0

下面是一個關於NVL的示例SQL問題。另一個帶日期的NVL

檢查PROGRAM表的結構。

CREATE TABLE programs (prog_id NOT NULL NUMBER(3), 
         prog_cost NUMBER(8, 2) 
         start_date NOT NULL DATE, 
         end_date DATE 
         ); 

哪兩個SQL語句會成功執行? (選擇兩項)。

A) SELECT nvl(add_months(end_date, 1), SYSDATE) 
from programs; 

B) SELECT to_date(nvl(SYSDATE - end_date, SYSDATE)) 
from programs; 

C) SELECT nvl(months_between(start_date, end_date), 'ongoing') 
from programs; 

D) SELECT nvl(to_char(months_between(start_date, end_date)), 'ongoing') 
from programs; 

對我來說,只要在節目表中的數據沒有給出,所有上述四個語句可以成功執行。

正確答案是A & D.答案沒有解釋。有誰知道作者是如何到達A & D.

回答

2

B和C在邏輯上有一些問題。還有臭名昭着的隱式轉換。

B) SELECT to_date(nvl(SYSDATE - end_date, SYSDATE)) 
from programs; 

表達式SYSDATE - end_date會給你兩個日期之間的間隔。由於它是數值,因此結果將有NUMBER數據類型。第二個參數(SYSDATE)是DATE。雖然隱式轉換可能實際上有助於避免異常,並給你一些數字結果,但我沒有真正理解,爲什麼有人需要將當前日期轉換爲數字。似乎很無用。

C) SELECT nvl(months_between(start_date, end_date), 'ongoing') 
from programs; 

好吧,我可以想象它的某種情況,雖然我可能會做它不同,但隱式轉換再次。

MONTHS_BETWEENdoc) 返回日期之間的月數。

所以第一個參數有一個NUMBER數據類型。通過'ongoing'字符串作爲第二個參數應該會提高無效號碼例外,除非您有一些非常奇怪的NLS參數。

+0

@that_young_man:謝謝 – anishjp

2

A和D作爲答案的原因歸結爲nvl函數中的數據類型不匹配。兩個參數必須是相同的類型。

with test_data as 
(
    select 1 as prog_id, 1 as prog_cost, to_date('10-12-2015', 'MM-dd-yyyy') as start_date, sysdate as end_date from dual 
    union all 
    select 2, null, to_date('10-12-2015', 'MM-dd-yyyy'), sysdate from dual 
    union all 
    select 3, 1, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
    union all 
    select 4, null, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
) 
select nvl(add_months(end_date, 1), sysdate) 
from test_data; 

上述執行並返回結果的所有記錄...

with test_data as 
(
    select 1 as prog_id, 1 as prog_cost, to_date('10-12-2015', 'MM-dd-yyyy') as start_date, sysdate as end_date from dual 
    union all 
    select 2, null, to_date('10-12-2015', 'MM-dd-yyyy'), sysdate from dual 
    union all 
    select 3, 1, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
    union all 
    select 4, null, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
) 
select to_date(nvl(SYSDATE - end_date, SYSDATE)) 
from test_data; 

因爲nvl的兩個參數是不相同的數據類型的上述引發錯誤ORA-01847: day of month must be between 1 and last day of month ...

with test_data as 
(
    select 1 as prog_id, 1 as prog_cost, to_date('10-12-2015', 'MM-dd-yyyy') as start_date, sysdate as end_date from dual 
    union all 
    select 2, null, to_date('10-12-2015', 'MM-dd-yyyy'), sysdate from dual 
    union all 
    select 3, 1, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
    union all 
    select 4, null, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
) 
select nvl(months_between(start_date, end_date), 'ongoing') 
from test_data; 

和上一個一樣,上面會拋出錯誤ORA-01722: invalid number,因爲nvl的兩個參數不是t他是相同的數據類型。 months_between返回一個數字,'ongoing'是一個varchar ...

最後一個作品,因爲它轉換的months_between返回到char ...

with test_data as 
(
    select 1 as prog_id, 1 as prog_cost, to_date('10-12-2015', 'MM-dd-yyyy') as start_date, sysdate as end_date from dual 
    union all 
    select 2, null, to_date('10-12-2015', 'MM-dd-yyyy'), sysdate from dual 
    union all 
    select 3, 1, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
    union all 
    select 4, null, to_date('10-12-2015', 'MM-dd-yyyy'), null from dual 
) 
select nvl(to_char(months_between(start_date, end_date)), 'ongoing') 
from test_data; 
+0

如果你包括在你的答案完全錯誤信息,而不僅僅是錯誤號這將有助於。 – Boneist

+0

@gmiley:謝謝。 – anishjp

相關問題