CASE 语句和 NVL 在 Oracle11G 中提供不同的输出

Posted

技术标签:

【中文标题】CASE 语句和 NVL 在 Oracle11G 中提供不同的输出【英文标题】:CASE Statement and NVL provides different output in Oracle11G 【发布时间】:2016-11-25 14:30:29 【问题描述】:

我有一个只有数字和空格的字符串。 我正在使用 CASE 和 NVL 函数来获取输出。 如果字符串为 NULL,则使用相同的字符串值,否则使用 1。 我能够为 SQL 和 PLSQL 提供不同的行为。 谁能提供一些关于这种行为的解释,哪一种是最好的方法。

SQL

NVL 函数可以在没有 TRIM 的情况下工作并提供结果

WITH T AS (SELECT ' 1234' LV FROM DUAL )
SELECT '"'||NVL(LV,1)||'"'  LV
FROM T;

LV    
-------
" 1234" 

CASE 给出 ORA-00932 错误

WITH T AS (SELECT ' 1234' LV FROM DUAL )
SELECT CASE WHEN LV IS NOT NULL THEN LV ELSE 1 END
FROM T;


Error report:
SQL Error: ORA-00932: inconsistent datatypes: expected CHAR got NUMBER
00932. 00000 -  "inconsistent datatypes: expected %s got %s"
*Cause:    
*Action:

PLSQL

NVL 提供带空格的结果

SET SERVEROUTPUT ON
DECLARE
LV VARCHAR2(10):=' 1234';
BEGIN
DBMS_OUTPUT.PUT_LINE('BEFORE CASE -"'||LV||'"');
LV:=NVL(LV,1);
DBMS_OUTPUT.PUT_LINE('AFTER CASE -"'||LV||'"');
END;

Result:
BEFORE CASE -" 1234"
AFTER CASE -" 1234"

案例陈述修剪结果

SET SERVEROUTPUT ON
DECLARE
LV VARCHAR2(10):=' 1234';
BEGIN
DBMS_OUTPUT.PUT_LINE('BEFORE CASE -"'||LV||'"');
LV:=CASE WHEN LV IS NOT NULL THEN LV ELSE 1 END;
DBMS_OUTPUT.PUT_LINE('AFTER CASE -"'||LV||'"');
END;

Result:
BEFORE CASE -" 1234"
AFTER CASE -"1234"

【问题讨论】:

WITH T AS ( SELECT ' 1234' LV FROM DUAL ) SELECT CASE WHEN LV IS NOT NULL THEN LV ELSE '1' END FROM T; 解释是Oracle就是这样做的。阅读有关 NVL functionCASE expressions 的 Oracle 文档。文档清楚地解释了当所涉及的数据类型都不同时每个行为的行为。 总有 COALESCE;这可能比 NVL 更快,因为它执行短路。 如果您不依赖隐式转换,COALESCE 不会修剪 SQL 或 PL/SQL 中的任何内容。 LV := coalesce(LV, '1') 可能是编写您的陈述的最佳方式 - 或者使用 CASE 但也使用 '1',而不是 1。您刚刚遇到了一个很好的说明,说明了为什么您应该在任何地方使用兼容的数据类型,而不是依赖 Oracle 来“忽略”一些不匹配并默默地为您提供“修复”:“修复”在最好的情况下是正确的. @hemalp108 我很难理解为什么这是一个问题。您得到的结果不一致,因为您没有使用正确的数据类型,并且不同的方法以不同的方式处理隐式转换。你知道你在寻找一个字符串,所以将 replace-for-null-value 定义为一个字符串,你不必担心任何事情。 【参考方案1】:

问题在于您的案例陈述。

CASE WHEN LV IS NOT NULL THEN LV ELSE 1 END

这里的 LV 是 varchar 类型,在 else 语句中,您将 1 分配为整数值,这为不同的数据类型带来了问题。

只需更新您的案例陈述,如下所述,它将在 oracle 中工作

CASE WHEN LV IS NOT NULL THEN LV ELSE '1' END

【讨论】:

以上是关于CASE 语句和 NVL 在 Oracle11G 中提供不同的输出的主要内容,如果未能解决你的问题,请参考以下文章

oracle的nvl

『ORACLE』 PLSQL-case语句(11g)

SQL语句case when

SQL nvl 等效 - 没有 if/case 语句 & isnull & coalesce

oracle 11g 表空间使用率

oracle数据库中nvl可以用于insert语句中吗?