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 function
和 CASE 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 中提供不同的输出的主要内容,如果未能解决你的问题,请参考以下文章