大数跨境

OceanBase 中 MySQL/Oracle 模式中的 NULL 与空字符串

OceanBase 中 MySQL/Oracle 模式中的 NULL 与空字符串 瑞蓝创软件
2026-07-07
2
导读:NULL 与空字符串 '',MySQL/Oracle 模式行为完全不一样

作者简介孙占涯瑞蓝创数据库工程师















原创内容未经授权不得随意使用,转载请联系小编并注明来源


OceanBase 一套内核兼容 MySQL 和 Oracle 两种租户模式,但对NULL、''(空串)的底层处理逻辑天差地别。本文基于 OB V4.2.1.7 实测验证,把两种模式下存储、查询、COUNT 统计、唯一索引四大核心场景讲透,看完直接规避线上故障。

一、总结

【NULL 与空字符串】一句话核心总结:

  • MySQL 模式:空串 '' 是普通字符串,与 NULL 完全不同;

  • Oracle 模式:空串 '' 被视为 NULL,两者等价;

操作场景
OB Oracle 模式
OB MySQL 模式
插入空串 ''
自动转为 NULL
保持为空串 ''
空串是否为 NULL
NULL
 与空串比较
不相等
不相等
COUNT(column)
不统计 NULL,不统计空串
不统计 NULL,统计空串
唯一索引中多个 NULL
不冲突(允许)
不冲突(允许)
唯一索引中多个空串
不冲突(因为被转为 NULL
冲突(不允许)

二、验证步骤-MySQL 模式

2.1 准备环境

创建 test_mysql_260527 表并插入 3 条数据,分别是:空字符串,NULL,正常值;

mysql -h192.168.xxx.xxx -P2883 -uroot@mysql_251126#ob_4255_251126 -p'xxx' -A -Dtest

CREATE TABLE test_mysql_260527 ( id INT, col_1 VARCHAR(50));           -- 创建测试表
INSERT INTO test_mysql_260527 VALUES (1''), (2NULL), (3'abc');   -- 插入测试数据,分别是:空字符串,NULL,正常值;
-- DROP TABLE test_mysql_260527;  -- 清理测试表
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 6572857
Server version: 5.6.25 OceanBase 4.2.1.7 (r107010022024060601-fe709b4735794f5e577d5b14f91d9183a12f101e) (Built Jun  6 2024 01:33:55)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type'\c'toclear the currentinput statement.

MySQL [test]> CREATETABLE test_mysql_260527 ( idINT, col_1 VARCHAR(50));           -- 创建测试表
Query OK, 0 rows affected (0.39 sec)

MySQL [test]> INSERTINTO test_mysql_260527 VALUES (1''), (2NULL), (3'abc');   -- 插入测试数据,分别是:空字符串,NULL,正常值;
Query OK, 3 rows affected (0.08 sec)
Records: 3  Duplicates: 0  Warnings: 0
2.2 验证 NULL 值和空字符串是否等价

在 V 4.2.1.7 版本的 MySQL 租户模式中,验证【null 值】和【''(即空值,空字符串)】的区别;验证结果:在 OB MySQL 模式中,以上 2 者是不等价的;

-- 【sql-01】查询空字符串(应返回 id=1 的行)
SELECT * FROM test_mysql_260527 WHERE col_1 = '';

-- 【sql-02】查询 NULL(应返回 id=2 的行)
SELECT * FROM test_mysql_260527 WHERE col_1 IS NULL;

-- 【sql-03】= NULL 语法不会返回任何结果(错误用法)
SELECT * FROM test_mysql_260527 WHERE col_1 = NULL;  -- 返回空集
MySQL [test]> SELECT * FROM test_mysql_260527 WHERE col_1 = '';
+------+-------+
| id   | col_1 |
+------+-------+
|    1 |       |
+------+-------+
1 row in set (0.01 sec)

MySQL [test]> SELECT * FROM test_mysql_260527 WHERE col_1 ISNULL;
+------+-------+
| id   | col_1 |
+------+-------+
|    2 | NULL  |
+------+-------+
1 row in set (0.01 sec)

MySQL [test]> SELECT * FROM test_mysql_260527 WHERE col_1 = NULL;  -- 返回空集
Empty set (0.00 sec)
2.3 验证 count 函数对 null 和 空字符串的处理

在 OB MySQL 模式中:count(col_1) 函数会忽略 NULL 值,所以预期结果为 2;

-- 【sql-04】验证 count 函数对 null 和 空字符串的处理(预期结果为:2)
SELECT count(col_1) FROM test_mysql_260527;
MySQL [test]> SELECT count(col_1) FROM test_mysql_260527;
+--------------+
| count(col_1) |
+--------------+
|            2 |
+--------------+
1 row in set (0.01 sec)
2.4 验证对唯一索引的影响

在 OB MySQL 模式中:唯一索引是允许 NULL 值重复的;空字符串是不允许重复的;所以第 1 条 insert 语句成功,第 2 条 insert 语句失败;

-- 【sql-05】验证对唯一索引的影响:
CREATE UNIQUE INDEX idx_unique_col_1 ON test_mysql_260527 (col_1);  -- 在 col_1 字段上创建唯一索引
INSERT INTO test_mysql_260527 VALUES (4NULL);
INSERT INTO test_mysql_260527 VALUES (5'');
MySQL [test]> CREATE UNIQUE INDEX idx_unique_col_1 ON test_mysql_260527 (col_1);
Query OK, 0 rows affected (0.81 sec)

MySQL [test]> INSERT INTO test_mysql_260527 VALUES (4NULL);
Query OK, 1 row affected (0.01 sec)

MySQL [test]> INSERT INTO test_mysql_260527 VALUES (5'');
ERROR 1062 (23000): Duplicate entry '' for key 'idx_unique_col_1'

三、验证步骤-Oracle 模式

3.1 准备环境

创建 test_oracle_260527 表并插入 3 条数据,分别是:空字符串,NULL,正常值;

obclient -h192.168.xxx.xxx -P2883 -uSYS@oracle_250917#ob_4255_251126 -p'xxx' -A

CREATE TABLE test_oracle_260527 ( id INT, col_1 VARCHAR(50));           -- 创建测试表
INSERT INTO test_oracle_260527 VALUES (1''), (2NULL), (3'abc');   -- 插入测试数据,分别是:空字符串,NULL,正常值;
-- DROP TABLE test_oracle_260527;  -- 清理测试表
Welcome to the OceanBase.  Commands end with ; or \g.
Your OceanBase connection id is 6572969
Server version: OceanBase 4.2.1.7 (r107010022024060601-fe709b4735794f5e577d5b14f91d9183a12f101e) (Built Jun  6 2024 01:33:55)

Copyright (c) 2000, 2018, OceanBase and/or its affiliates. All rights reserved.

Type 'help;' or '\h' for help. Type'\c'toclear the currentinput statement.

obclient(SYS@oracle_250917)[SYS]> CREATETABLE test_oracle_260527 ( idINT, col_1 VARCHAR(50));           -- 创建测试表
Query OK, 0 rows affected (0.369 sec)

obclient(SYS@oracle_250917)[SYS]> INSERTINTO test_oracle_260527 VALUES (1''), (2NULL), (3'abc');   -- 插入测试数据,分别是:空字符串,NULL,正常值;
Query OK, 3 rows affected (0.054 sec)
Records: 3  Duplicates: 0  Warnings: 0
3.2 验证 NULL 值和空字符串是否等价

使用 insert into 语句插入【''(空字符串)】时,OB 会自动将其转换成 NULL 值并存储,但是在查询时(where 条件中),若使用【''(空字符串)】则不能查出数据,必须使用 IS NULL 或 IS NOT NULL

-- 【sql-01】查询空字符串(返回空集)
SELECT * FROM test_oracle_260527 WHERE col_1 = '';

-- 【sql-02】查询 NULL(应返回 id = 1/2 的行)
SELECT * FROM test_oracle_260527 WHERE col_1 IS NULL;

-- 【sql-03】= NULL 语法不会返回任何结果(错误用法)(返回空集)
SELECT * FROM test_oracle_260527 WHERE col_1 = NULL
obclient(SYS@oracle_250917)[SYS]> SELECT * FROM test_oracle_260527 WHERE col_1 = '';
Empty set (0.002 sec)

obclient(SYS@oracle_250917)[SYS]> SELECT * FROM test_oracle_260527 WHERE col_1 IS NULL;
+------+-------+
| ID   | COL_1 |
+------+-------+
|    1 | NULL  |
|    2 | NULL  |
+------+-------+
2 rows in set (0.008 sec)

obclient(SYS@oracle_250917)[SYS]> SELECT * FROM test_oracle_260527 WHERE col_1 = NULL
Empty set (0.004 sec)
3.3 验证 count 函数对 null 和 空字符串的处理

在 OB Oracle 模式中:count(col_1) 函数会忽略 NULL 值,正常来说查询结果应该为 2,但是在 OB Oracle 模式中,会将【''(空字符串)】转换成 NULL 值并存储,所以查询结果预期为 1;

-- 【sql-04】验证 count 函数对 null 和 空字符串的处理(预期结果为:1)
SELECT count(col_1) FROM test_oracle_260527;
obclient(SYS@oracle_250917)[SYS]> SELECT count(col_1) FROM test_oracle_260527;
+--------------+
| COUNT(COL_1) |
+--------------+
|            1 |
+--------------+
1 row in set (0.003 sec)
3.4 验证对唯一索引的影响

在 OB Oracle 模式中:唯一索引是允许 NULL 值重复的;空字符串会被转换成 NULL 值并存储,所以也是允许重复的;即 2 条 insert 语句都能执行成功;

-- 【sql-05】验证对唯一索引的影响:
CREATE UNIQUE INDEX idx_unique_col_1 ON test_oracle_260527 (col_1);  -- 在 col_1 字段上创建唯一索引
INSERT INTO test_oracle_260527 VALUES (4NULL);
INSERT INTO test_oracle_260527 VALUES (5'');
obclient(SYS@oracle_250917)[SYS]> CREATE UNIQUE INDEX idx_unique_col_1 ON test_oracle_260527 (col_1); 
Query OK, 0 rows affected (0.864 sec)

obclient(SYS@oracle_250917)[SYS]> INSERT INTO test_oracle_260527 VALUES (4NULL);
Query OK, 1 row affected (0.003 sec)

obclient(SYS@oracle_250917)[SYS]> INSERT INTO test_oracle_260527 VALUES (5'');
Query OK, 1 row affected (0.003 sec)

PS:本文关于以上所有验证都是在 V 4.2.1.7 版本的 OB 集群中进行。



如果在操作过程中遇到问题,欢迎在评论区留言交流,后续我们会持续分享更多实战运维干货,记得关注不迷路,下次见~

END


瑞蓝创 OceanBase OBCP V4 精英训练营

点击下方图片立即了解详情


··


·

·

▼ 点击「阅读原文」,了解更多产品技术文章

【声明】内容源于网络
0
0
瑞蓝创软件
专注于企业信息科技战略咨询、数据中心规划及运维、智能化软件产品研发,致力于为金融、能源、电信、制造等行业提供智能的业务永续及流程自动化解决方案。
内容 51
粉丝 0
瑞蓝创软件 专注于企业信息科技战略咨询、数据中心规划及运维、智能化软件产品研发,致力于为金融、能源、电信、制造等行业提供智能的业务永续及流程自动化解决方案。
总阅读348
粉丝0
内容51