oracle - 遵守传统空值处理的连接
问题描述
SQL 和语言规范中的常规处理null
是,如果表达式的任何部分是null
,则整个表达式是null
。
但是在 Oracle 中,文本连接转换null
为 a <blank>
,例如:
select concat(concat('foo', null), 'bar') from dual; --> returns "foobar"
select 'foo' || null || 'bar' from dual; --> returns "foobar"
null
我想要传统的行为,如果任何术语为空,结果将是。
Oracle 是否提供了一种方法或函数,它使用单个表达式连接文本,而不重新编码任何术语,这样如果任何术语是null
,结果是null
?
笔记:
- 我不想重复任何条款,这将是
case
etc 所要求的,因为这些条款非常长且复杂,而且重复代码是不好的做法 - 我无法定义任何功能。我必须只使用一个 SQL 查询,只使用标准语法和纯 Oracle 提供的函数/运算符
- 通过使用子查询或 CTE 来回避不重复要求并不能回答问题,而是在避免它:我想知道 Oracle 是否可以像我知道的所有其他数据库一样使用单个表达式连接字符串
解决方案
我不喜欢一个SQL
函数,并且这种 NULL 行为VARCHAR2
是可能的常规行为,但肯定不是通常预期的。NULL
原因是 Oracle 在和长度为零的字符串 ('')之间没有区别。对于字符串连接,NULL 被视为空字符串。
无论如何,您可以使用子查询来避免重复表达式:
with t1 as (
select 'foo' col1, null col2, 'bar' col3 from dual union all
select null col1, null col2, null col3 from dual union all
select 'foo' col1, 'baz' col2, 'bar' col3 from dual
)
select col1,col2,col3,
case when col1 is not NULL and col2 is not NULL and col3 is not NULL then
col1||col2||col3 end as concat
from t1;
返回
COL COL COL CONCAT
--- --- --- ---------
foo bar
foo baz bar foobazbar
或者,您可以使用组比较条件在 tehCASE
语句中编写更紧凑的谓词
select
case when 0 < ALL(length(col1),length(col2),length(col3)) then
col1||col2||col3 end as concat
from t1;
不幸的是,组比较条件不允许直接IS NULL
测试,因此length
必须使用解决方法。
第三个选项有点难看(因为需要一些常规字符串中不存在的特殊字符串,但可能最符合您的要求。
在连接之前简单NVL
所有字符串,而不是排除那些 mappend byNVL
with t2 as
(select nvl(col1,'#§$%')||nvl(col2,'#§$%')||nvl(col3,'#§$%') as concat
from t1)
select
case when concat not like '%#§$\%%' escape'\' then concat end as concat
from t2;
推荐阅读
- docker - 如何让 Docker 使用所有 CPU 内核?
- matlab - 使用一组开始和结束索引对数组进行索引
- powershell - 如何在 cmd 的 PowerShell 调用中包含参数?
- bash - 如何创建/管理作业队列
- java - 一个topic有4个队列,只消费一个
- azure-data-factory-2 - Azure 数据工厂中是否有任何选项可以在从源系统复制数据时保留相同的日期格式
- fortran - 从文本读取并写入二进制
- html - CSS 选择器,它指向一个悬停的元素,它的五个相邻兄弟元素中的每一个都在两个方向上
- spring-integration - Spring Integration DSL HTTP 出站网关支持字节数组作为有效负载
- typescript - 返回类型是从参数计算键的对象