首页 > 解决方案 > 使用/不使用 CASE 语句时,Oracle NVL 返回不一致的结果

问题描述

任何人都可以帮助我理解为什么 oracle db 在使用/不使用 CASE 语句时返回不一致的结果。

SELECT NVL(CASE WHEN '' IS NULL THEN NULL ELSE NULL END ,TO_DATE('19010101', 'YYYYMMDD')) a,
   NVL(CASE WHEN '' IS NOT NULL THEN NULL ELSE NULL END ,TO_DATE('19010101', 'YYYYMMDD')) b,
   NVL(CASE WHEN '' = '' THEN NULL ELSE NULL END ,TO_DATE('19010101', 'YYYYMMDD')) c,
   NVL(NULL ,TO_DATE('19010101', 'YYYYMMDD')) d from dual;

运行结果

我的实际查询使用TRUNC(NVL(:NEW_FORM_TIME_END, TO_DATE('19010101', 'YYYYMMDD'))) >= TRUNC(SYSDATE - INTERVAL '2' DAY)whereNEW_FORM_TIME_END可能是空字符串或 NULL 但我收到此错误ORA-06550: line 240, column 91: PLS-00306: wrong number or types of arguments in call to '>=' ORA-06550: line 229, column 9: PL/SQL: Statement ignored

标签: phporaclecaseoracle18cnvl

解决方案


VARCHAR2如果您不提供显式类型,则您的案例表达式属于默认类型。NULL文字没有类型。NVL(<varchar2>, <date>)<date>参数应用隐式类型转换。在其他 RDBMS 中,您只会因为不兼容的类型而得到错误。您的表达式的 PL/SQL 版本可能也会遇到类似的问题,尽管与您在查询中呈现的问题不完全相同。

只要确保你总是比较相同的类型。

试试这个来检查:

SELECT 
  NVL(CAST(CASE WHEN '' IS NULL THEN NULL END AS DATE), DATE '1901-01-01') a,
  NVL(CAST(CASE WHEN '' IS NOT NULL THEN NULL END AS DATE), DATE '1901-01-01') b,
  NVL(CAST(CASE WHEN '' = '' THEN NULL END AS DATE), DATE '1901-01-01') c,
  NVL(NULL, DATE '1901-01-01') d
FROM dual;

或者,从您的表中创建一个视图,然后检查字典:

CREATE VIEW v AS
SELECT 
  NVL(CASE WHEN '' IS NULL THEN NULL END, DATE '1901-01-01') a,
  NVL(CASE WHEN '' IS NOT NULL THEN NULL END, DATE '1901-01-01') b,
  NVL(CASE WHEN '' = '' THEN NULL END, DATE '1901-01-01') c,
  NVL(NULL, TO_DATE('19010101', 'YYYYMMDD')) d
FROM dual;

SELECT column_name, data_type
FROM all_tab_cols
WHERE table_name = 'V'
ORDER BY column_name;

屈服

|COLUMN_NAME|DATA_TYPE|
|-----------|---------|
|A          |VARCHAR2 |
|B          |VARCHAR2 |
|C          |VARCHAR2 |
|D          |DATE     |

推荐阅读