为什么 NVL() 在以下外连接 (+) 中不起作用?
Why NVL() doesn't work in the following outer join(+)?
我正在尝试对两个表进行外连接,当"Full Name"列中显示空值时,将其替换为'No one'。
外连接工作正常,问题是,空值仍然是空值,而不是'No one'。
以下是我的代码。
SELECT
NVL(to_char(e.FIRST_NAME||' '||e.LAST_NAME),'No One') "Full Name",
d.DEPARTMENT_NAME
FROM EMPLOYEES e,DEPARTMENTS d
WHERE e.DEPARTMENT_ID(+)=d.DEPARTMENT_ID;
下面是结果截图。
感谢观看!
"NVL does not work" 因为 NVL 的参数中总是至少有一个 space 字符。
SELECT
decode(e.FIRST_NAME||e.LAST_NAME,null,'No one',e.FIRST_NAME||' '||e.LAST_NAME) "Full Name",
d.DEPARTMENT_NAME
FROM EMPLOYEES e,DEPARTMENTS d
WHERE e.DEPARTMENT_ID(+)=d.DEPARTMENT_ID;
可能是一个可行的替代方案。
因为表达式 e.FIRST_NAME||' '||e.LAST_NAME
永远不会为空。如果该行是外部连接的,则值为 ' '
.
与其他数据库不同,Oracle 允许在字符串中串联 NULL
个值。
我会将您的查询写成:
SELECT (CASE WHEN e.FIRST_NAME IS NULL AND e.LAST_NAME IS NULL THEN 'No One'
WHEN e.FIRST_NAME IS NULL THEN e.LAST_NAME
WHEN e.LAST_NAME IS NULL THEN e.FIRST_NAME
ELSE e.FIRST_NAME || ' ' || e.LAST_NAME
END) "Full Name", d.DEPARTMENT_NAME
FROM DEPARTMENTS d LEFT JOIN
EMPLOYEES e
ON e.DEPARTMENT_ID = d.DEPARTMENT_ID;
备注:
- 这使用了正确的显式
JOIN
语法。连接的 (+)
表示法是古老的且已弃用。您应该学习正确的显式 JOIN
语法。
- 当其中一个值缺失时,逻辑不再在名称的 beginning/end 处有额外的空格。
- 逻辑明确并使用 ANSI 标准
CASE
表达式。
此外,还有一些奇特的方法可以缩短表达式:
coalesce(trim(e.FIRST_NAME || ' ' || e.LAST_NAME), 'No One')
我只是觉得case
逻辑更清晰。
由于还没有人提到它,您可以使用 NVL2,其形式为:
NVL2(<expression>, <value if expression is not null>, <value if expression is null>)
所以你可以简单地做:
NVL2(e.FIRST_NAME||e.LAST_NAME, TRIM(e.FIRST_NAME||' '||e.LAST_NAME), 'No One') "Full Name"
TRIM 的情况是名字或姓氏可能为空(但不能同时为空);它会删除剩下的 trailing/leading space。
我正在尝试对两个表进行外连接,当"Full Name"列中显示空值时,将其替换为'No one'。
外连接工作正常,问题是,空值仍然是空值,而不是'No one'。
以下是我的代码。
SELECT
NVL(to_char(e.FIRST_NAME||' '||e.LAST_NAME),'No One') "Full Name",
d.DEPARTMENT_NAME
FROM EMPLOYEES e,DEPARTMENTS d
WHERE e.DEPARTMENT_ID(+)=d.DEPARTMENT_ID;
下面是结果截图。
感谢观看!
"NVL does not work" 因为 NVL 的参数中总是至少有一个 space 字符。
SELECT
decode(e.FIRST_NAME||e.LAST_NAME,null,'No one',e.FIRST_NAME||' '||e.LAST_NAME) "Full Name",
d.DEPARTMENT_NAME
FROM EMPLOYEES e,DEPARTMENTS d
WHERE e.DEPARTMENT_ID(+)=d.DEPARTMENT_ID;
可能是一个可行的替代方案。
因为表达式 e.FIRST_NAME||' '||e.LAST_NAME
永远不会为空。如果该行是外部连接的,则值为 ' '
.
与其他数据库不同,Oracle 允许在字符串中串联 NULL
个值。
我会将您的查询写成:
SELECT (CASE WHEN e.FIRST_NAME IS NULL AND e.LAST_NAME IS NULL THEN 'No One'
WHEN e.FIRST_NAME IS NULL THEN e.LAST_NAME
WHEN e.LAST_NAME IS NULL THEN e.FIRST_NAME
ELSE e.FIRST_NAME || ' ' || e.LAST_NAME
END) "Full Name", d.DEPARTMENT_NAME
FROM DEPARTMENTS d LEFT JOIN
EMPLOYEES e
ON e.DEPARTMENT_ID = d.DEPARTMENT_ID;
备注:
- 这使用了正确的显式
JOIN
语法。连接的(+)
表示法是古老的且已弃用。您应该学习正确的显式JOIN
语法。 - 当其中一个值缺失时,逻辑不再在名称的 beginning/end 处有额外的空格。
- 逻辑明确并使用 ANSI 标准
CASE
表达式。
此外,还有一些奇特的方法可以缩短表达式:
coalesce(trim(e.FIRST_NAME || ' ' || e.LAST_NAME), 'No One')
我只是觉得case
逻辑更清晰。
由于还没有人提到它,您可以使用 NVL2,其形式为:
NVL2(<expression>, <value if expression is not null>, <value if expression is null>)
所以你可以简单地做:
NVL2(e.FIRST_NAME||e.LAST_NAME, TRIM(e.FIRST_NAME||' '||e.LAST_NAME), 'No One') "Full Name"
TRIM 的情况是名字或姓氏可能为空(但不能同时为空);它会删除剩下的 trailing/leading space。