在PostgreSQL和Oracle中,什么时候对待空值和空字符串是一样的?

cwtwac6a  于 2022-10-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(165)

我创建了以下的dbfiddle,在其中您可以看到field<>‘排除了field为空的情况。

https://www.db-fiddle.com/f/xdfayYMvdRZDRRASvGFdpT/0

CREATE TABLE test (
  prd_typ_cd bpchar,
  prd_prnt_typ_cd bpchar,
  prd_chld_typ_cd bpchar
);
INSERT INTO test VALUES ('SHC', null, 'DIV');

INSERT INTO test VALUES ('DIV', 'SHC', 'DEP');

INSERT INTO test VALUES ('DEP', 'DIV', null);

SELECT * FROM test WHERE prd_chld_typ_cd <> '';

我很惊讶地看到了这一点,因为在大多数语言中,NULL和‘’(空字符串)被区别对待。

上面的例子来自于一个PostgreSQL数据库。在Oracle数据库上也是如此吗?在什么情况下,PostgreSQL和Oracle会将NULL和‘’(空字符串)视为同一事物?

5gfr0r5j

5gfr0r5j1#

在postgres中,NULL''*受到不同的处理。

prd_chld_typ_cd <> ''

prd_chld_typ_cdNULL时,返回NULL。这是涉及NULL的大多数操作的典型行为。您会很容易地发现:

prd_chld_typ_cd = ''

当该列为NULL时,其行为完全相同。

对于任何其他值,该表达式返回TRUE或FALSE。如果返回值,您将很容易看到以下内容:

SELECT t.*, prd_chld_typ_cd <> ''
FROM test t;

实际情况是,NULL和False在WHERE筛选器中被以相同的方式处理--两者都筛选出行。

相比之下,NULL''在Oracle中是同义词。但事实证明,

prd_chld_typ_cd <> ''
 prd_chld_typ_cd = ''

prd_chld_typ_cdNULL时,两者的行为相同。遗憾的是,在Oracle中,两者都返回NULL--因为''等同于NULL

xdnvmnnf

xdnvmnnf2#

我不知道Postgres,但如果您计划在您的应用程序中支持它,Oracle有一些关于空字符串的怪癖需要注意:

1.在Oracle中,空字符串始终被视为空字符串:如果插入空字符串,则将回读空字符串。在Oracle中,空字符串根本不存在:在处理varchar值时,如果您可以编写‘’而不是NULL,那么空字符串就是“语法糖”。
1.在Oracle中,表达式(‘’IS NULL)的计算结果为TRUE。空字符串实际上为空
1.在Oracle中,任何涉及空值的比较都将始终计算为FALSE。这意味着可以应用于空值并且可以返回TRUE的运算符只有“is NULL”和“is NOT NULL”

上面的结果是,在Oracle中,无论myvar的实际值是多少,以下所有表达式的计算结果都将为FALSE:

myvar = '' 
 myvar <> '' 
 myvar = null
 myvar <> null

即使是这些评估也总是错误的

null = null
 null <> null
 null = '' 
 null <> ''

因此,以下更新不会更新任何内容:

update mytab set myfield ='X' where myfield = ''

正如我所说的,您只能使用‘IS NULL’和‘IS NOT NULL’运算符。所以你必须把它写成

update mytab set myfield='X' where myfield is null.

另外,唯一将NULL视为不同的可比值的Oracle函数是Decode()。这可能是一个错误,但今天有太多的软件依赖于这一行为来修复它。

decode( <expression>,
          <caseval 1>,  < exitval 1>,
          <caseval 2>,  < exitval 2>,
          .... 
           <elseval>)

如果将“decode”替换为等价的SQL标准“case”构造,它将不起作用:Oracle在实现CASE语法时没有复制解码错误

相关问题