另一个带日期的NVL

时间:2016-02-18 14:42:09

标签: sql oracle11g

以下是有关NVL的SQL问题示例。

检查PROGRAMS表的结构。

input_var=raw_input("Enter path:" )
files=[]

for dirpath, dirnames, filenames in os.walk(input_var):
    for fname in filenames:
        fullname = os.path.join(dirpath, fname)
        print(pwd.getpwuid(os.stat(fullname).st_uid).pw_name)

哪两个SQL语句会成功执行? (选择两个。)

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

对我来说,只要没有给出程序表中的数据,就可以成功执行上述四个语句。

正确答案是A& D.答案没有解释。有谁知道作者如何到达A& D.

2 个答案:

答案 0 :(得分: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_BETWEEN   (doc)   返回日期之间的月数。

因此第一个参数具有NUMBER数据类型。将'ongoing'字符串作为第二个参数传递会引发无效数异常,除非您有一些非常奇怪的NLS参数。

答案 1 :(得分: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;

上面引发错误ORA-01847: day of month must be between 1 and last day of month,因为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(months_between(start_date, end_date), 'ongoing')
from test_data;

与前一个类似,上面引发错误ORA-01722: invalid number,因为nvl的两个参数不是相同的数据类型。 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;