我无法理解这条sql执行后oracle数据库中发生了什么:
CREATE TABLE EMPTYSTRING
(
COLUMNA VARCHAR2(1)
);
INSERT INTO EMPTYSTRING (COLUMNA) VALUES('X');
ALTER TABLE EMPTYSTRING ADD
(
COLUMNB VARCHAR2(1) DEFAULT '' NOT NULL
);
据我所知,oracle 将空字符串视为空值。但是为什么添加一个具有默认“空”值的列和一个值不能为空的约束是合法的呢?
更重要的是,既然是合法的,那么内部是如何处理的呢? 如果我们尝试
SELECT * FROM EMPTYSTRING WHERE COLUMNB='';
SELECT * FROM EMPTYSTRING WHERE COLUMNB IS NULL;
我们没有得到任何结果。另一方面,如果我们尝试
SELECT * FROM EMPTYSTRING;
SELECT * FROM EMPTYSTRING WHERE TRIM(COLUMNB) IS NULL;
我们得到:
COLUMNA COLUMNB
------- -------
X
那么数据库中到底写了什么?为什么会这样?
如果我们尝试插入一行而不指定 COLUMNB 值
INSERT INTO EMPTYSTRING (COLUMNA) VALUES('Y');
我们收到“无法插入 NULL”错误,因此默认为空字符串实际上不起作用,除了我们添加 COLUMNB 之前表中的行。
ALTER TABLE EMPTYSTRING ADD ( COLUMNB VARCHAR2(1) DEFAULT '' NOT NULL );
据我所知,oracle 将空字符串视为空值。但是为什么添加一个具有默认“空”值的列和一个值不能为空的约束是合法的呢?
SGBD 不负责验证您的约束是否具有逻辑意义。 DEFAULT 约束用于将默认值插入到列中。如果未指定其他值,则默认值将添加到所有新记录中。 Oracle 不会检查默认值是否符合其他约束,因此如果您以这种方式编写约束,Oracle 将不会发出错误信号(不会有 ORA 错误消息)。当您尝试在未定义 COLUMNB 的值的情况下插入记录时,就会出现问题。
首先它会尝试将 '' (为 NULL)赋予 COLUMNB,然后它将应用为 COLUMB 定义的约束(确保该值不为 NULL)。这将导致错误 ORA-01407,表示 cannot update(...) to NULL。
从空字符串中选择 * WHERE COLUMNB='';
从空字符串中选择*,其中列为空;
在Oracle中我们不能写sth = null(表示它是否为null)。如果我们有两个 null 值,它们仍然不同(null 被定义为不等于其自身)。检查 COLUMNB 是否为空的唯一方法是使用 IS NULL。因此,即使 COLULMNB 实际上确实有空值,第一个也不会返回任何行。第二个将返回 COLUUMNB 具有空值的行,但由于 NOT NULL 约束,不存在这样的行。
我运行了前 3 个 SQL 语句,并在运行第三个 SQL 语句来添加带有
DEFAULT '' NOT NULL
的列时,出现以下错误:
[42000][1758] ORA-01758:表必须为空才能添加强制(非空)列位置:12
此外,如果我将此
ALTER
语句修改为 DEFAULT 'H' NOT NULL
,那么表中之前的 NULL
条目将具有 H
值,与 @Blood-HaZaRd 在评论中所写的不同。
其次,如果我插入可空列
NULL
或 ''
,此 SQL 将返回所有结果,正如 @Blood-HaZaRd 在他的答案中提到的:
SELECT * FROM EMPTYSTRING WHERE COLUMNB IS NULL;
我的Oracle版本是gvenzl/oracle-xe:21.3.0-slim。