2
SELECT inv_no,NVL2(inv_amt,inv_date,'Not Available')
FROM invoice;

SELECT inv_no,NVL2(inv_amt,inv_amt*.25,'Not Available') FROM invoice;

得到

ORA-01858: a non-numeric character was found where a numeric was expected
ORA-01722: invalid number

请分别建议我可以在 expr1 和 expr2 中给出哪些数据类型。

另外请告诉我这是怎么回事?

SELECT inv_no,NVL2(inv_date,sysdate-inv_date,sysdate)
FROM invoice
4

3 回答 3

6

第二个和第三个参数NVL2应该是相同的数据类型。所以,假设inv_date是一个日期,你需要varchar2像这样;

SELECT inv_no, NVL2(inv_amt, to_char(inv_date, 'dd-mon-yyyy hh24:mi:ss'), 'Not Available') FROM ...

或您想要的任何格式字符串。否则 Oracle 将转换第三个参数'Not Available'以匹配第二个参数的数据类型。这将尝试转换'Not Available'为日期并崩溃。

同样在第二个示例中,您必须通过 将 转换inv_amt*.25为 char to_char,例如to_char(inv_amt*.25)

于 2013-02-12T14:04:42.080 回答
1

您的前 2 个示例尝试为同一字段提供日期/数字和文本结果。当 Oracle 尝试将此文本转换为任一类型时,这将导致错误。您需要使用to_char(field)日期/数字字段上的函数将它们转换为文本。

最后,日期实际上是添加到数据库基准日期的数字。例如,日期是一个基日数,它的小数是一天的比率,例如 0.5 是 12 小时,并且数据库有一个基日,例如01-Jan-190001-Jan-2000。这就是为什么当你这样做时date - date结果是一个数字,而日期也可以表示为一个数字。

于 2013-02-13T09:56:37.983 回答
1

参考:https ://docs.oracle.com/cd/B19306_01/server.102/b14200/functions106.htm

第二个参数应该是字符或数字。第二个参数给出了第三个参数将被隐式转换的数据类型。所以:

1. 第一个
SELECT inv_no,NVL2(inv_amt,inv_date,'Not Available') FROM invoice;
不正确,因为您不能将 DATE 作为第二个参数。

一样的方法:

SELECT NVL2(NULLIF(1, 1), SYSDATE, 'A') FROM DUAL; -- FAILS;
SELECT NVL2(NULLIF(1, 0), SYSDATE, 'A') FROM DUAL; -- FAILS;
SELECT NVL2(NULLIF(1, 1), 'A', SYSDATE) FROM DUAL; -- PASS; returns SYSDATE (as char datatype)
SELECT NVL2(NULLIF(1, 0), 'A', SYSDATE) FROM DUAL; -- PASS; returns 'A';

2. 第二个也是无效的:
SELECT inv_no,NVL2(inv_amt,inv_amt*.25,'Not Available') FROM invoice;
Oracle 尝试将第三个参数隐式转换为第二个参数的数据类型,这意味着它尝试将“不可用”转换为数值。

当您交换第二个和第三个参数时,它将起作用:

SELECT inv_no,NVL2(inv_amt,'Not Available',inv_amt*.25) FROM invoice;

inv_amt*.25 将隐式转换为字符数据;这个例子是无用的,因为它会让你 NULL*.25 使它成为 NULL。

但是,您可以做的是,您可以通过将数字结果转换为字符来将两个参数都设为字符:

SELECT inv_no,NVL2(inv_amt,TO_CHAR(inv_amt*.25), 'Not Available') FROM invoice;

尤其是当您想显示货币时,这会很有意义。

3.第三个比较复杂

我能解释的唯一方法是在处理第三个参数之前将第二个参数转换为字符。这样第三个也将转换为字符。考虑到这两种情况,这是有道理的:

SELECT NVL2(2, SYSDATE - TO_DATE('10-JAN-83'), SYSDATE) from dual; -- PASSES
SELECT NVL2(2, 2.2, SYSDATE) from dual; -- FAILS.

最后:我建议坚持 Oracle 的文档并使用显式转换。

于 2017-06-22T06:28:44.350 回答