添加带有空字符串的列作为默认值而不是null约束会导致oracle数据库的行为不一致

01t*_*lav 5 string oracle null default-value

执行此sql后,我无法理解oracle数据库中会发生什么:

CREATE TABLE EMPTYSTRING
( 
COLUMNA VARCHAR2(1)
);

INSERT INTO EMPTYSTRING (COLUMNA) VALUES('X');

ALTER TABLE EMPTYSTRING ADD
(
COLUMNB VARCHAR2(1) DEFAULT '' NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

在我读到的文章中,oracle将空字符串视为null。但是,为什么要添加一个具有默认“空”值和一个约束的列,该约束说值不能为空合法值呢?

更重要的是,由于这是合法的,因此如何内部处理?如果我们尝试

SELECT * FROM EMPTYSTRING WHERE COLUMNB='';
SELECT * FROM EMPTYSTRING WHERE COLUMNB IS NULL;
Run Code Online (Sandbox Code Playgroud)

我们没有结果。另一方面,如果我们尝试

SELECT * FROM EMPTYSTRING;
SELECT * FROM EMPTYSTRING WHERE TRIM(COLUMNB) IS NULL;
Run Code Online (Sandbox Code Playgroud)

我们得到:

COLUMNA COLUMNB
------- -------
X               
Run Code Online (Sandbox Code Playgroud)

那么,真正写在数据库中的是什么?为什么会这样呢?

如果我们尝试插入一行而未为COLUMNB指定值

INSERT INTO EMPTYSTRING (COLUMNA) VALUES('Y');
Run Code Online (Sandbox Code Playgroud)

我们会收到“无法插入NULL”错误,因此默认情况下,除非添加COLUMNB之前表中的行,否则默认为空字符串实际上不起作用。

Blo*_*aRd 4

ALTER TABLE EMPTYSTRING ADD
(
   COLUMNB VARCHAR2(1) DEFAULT '' NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

据我所知,oracle 将空字符串视为空值。但是为什么添加一个具有默认“null”值的列和一个值不能为 null 的约束是合法的呢?

SGBD 不负责验证您的约束是否具有逻辑意义。DEFAULT约束用于将默认值插入到列中。如果未指定其他值,则默认值将添加到所有新记录中。Oracle 不会检查默认值是否符合其他约束,因此如果您以这种方式编写约束,Oracle 将不会发出错误信号(不会有 ORA 错误消息)。当您尝试插入一条记录而不定义COLUMNB的值时,就会出现问题。

首先,它将尝试将“”(为 NULL)赋予 COLUMNB,然后应用为 COLUMB 定义的约束(确保该值不为 NULL)。这将导致错误ORA-01407,指出无法 update(...) to NULL

从 EMPTYSTRING WHERE COLUMNB='' 中选择 *;

SELECT * FROM EMPTYSTRING WHERE COLUMNB 为空;

在Oracle中我们不能写sth = null(表示它是否为null)。如果我们有两个 null 值,它们仍然不同(null 被定义为不等于其自身)。检查 COLUMNB 是否为 null 的唯一方法是使用IS NULL。因此,即使 COLULMNB 实际上确实有空值,第一个也不会返回任何行。第二个将返回 COLUUMNB 具有空值的行,但由于 NOT NULL 约束,不存在这样的行。