其实用到 NULL 的场景都可以转换为有意义的字符或者数值,一是有利用数据的易读性以及后期的易维护性;二是降低 SQL 语句的编写难度。
关于 NULL 的特性如下:
1. 参与 NULL 字段拼接的结果都为 NULL,预期的可能会有差异
预想把字段 r1 做个拼接,再插入到新的表 t3 里,结果 t3 表的记录全为 NULL,跟预期不符。
mysql>show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`r1` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql>show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`r1` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql>create table t3 like t1
Query OK, 0 rows affected (0.04 sec)
mysql>insert into t3 select concat(r1,'database') from t1 limit 2
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql>select * from t3
+------+
| r1 |
+------+
| NULL |
| NULL |
+------+
2 rows in set (0.00 sec)
那正确的方法如下,对 NULL 用函数 IFNULL 特殊处理。
mysql>insert into t3 select concat(ifnull(r1,''),'database') from t1 limit 2
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql>select * from t3
+----------+
| r1 |
+----------+
| database |
| database |
+----------+
2 rows in set (0.00 sec)
2. 对于包含 NULL 列的求 COUNT 值也不准确
t1 和 t2 的记录数是一样的,但是字段 r1 包含了 NULL,这导致结果忽略了这些值。
mysql>select count(r1) as rc from t1
+-------+
| rc|
+-------+
| 16384 |
+-------+
1 row in set (0.01 sec)
mysql>select count(r1) as rc from t2
+-------+
| rc|
+-------+
| 32768 |
+-------+
1 row in set (0.03 sec)
这时候我们可能想到了,正确的方法是用 NULL 相关函数处理,
mysql>select count(ifnull(r1,'')) as rc from t1
+-------+
| rc|
+-------+
| 32768 |
+-------+
1 row in set (0.03 sec)
或者是直接用 COUNT(*) 包含了所有可能的值
mysql>select count(*) as rc from t1
+-------+
| rc|
+-------+
| 32768 |
+-------+
1 row in set (0.02 sec)
当然了不仅仅是 COUNT,除了 NULL 相关的函数,大部分对 NULL 处理都不友好。
所以其实从上面两点来看,NULL 的处理都得特殊处理,额外增加了编写 SQL 的难度。
3. 包含 NULL 的索引列
对包含 NULL 列建立索引,比不包含的 NULL 的字段,要多占用一个 BIT 位来存储。
示例
key_len 分别为 43 和 42,t1 比 t2 多了一个字节,那这里可能有人要问了,不是说占了一个 BIT 位吗?那为什么多了一个字节?可以关注我上一篇文章(第02期:MySQL 数据类型的艺术 - 大对象字段)关于 BIT 的详细描述。
mysql>pager grep -i 'key_len'
PAGER set to 'grep -i 'key_len''
mysql>explain select * from t1 where r1 = ''\G
key_len: 43
1 row in set, 1 warning (0.00 sec)
mysql>explain select * from t2 where r1 = ''\G
key_len: 42
1 row in set, 1 warning (0.00 sec)
4. 各存储引擎相关的对 NULL 的处理
在 MySQL 8.0 发布后,仅有 InnoDB、MyISAM 和 Memory 支持对包含 NULL 列的索引,其他引擎不支持。比如 NDB。
DELETE FROM Person WHERE LastName = 'Wilson'或
deltet from pdrson
删除后
commit
约束是什么约束?唯一性约束还是主键约束,条件约束,可能是外键约束,也就是这行数据的某个字段是另一个表的主键,当然不允许删除,
图片的顺序有点问题,应该是复制职员表那题在前面1、假设db_shop库中有一张名叫staffer的职员表,那么复制表包括记录的sql就是 create table db_shop.staffer_bak2 select * from db_shop.staffer
2、查看staffer_bak2 表结构的sql是 desc db_shop.staffer_bak2
3、给staffer_bak2 表添加字段,这题因为我不知道原本的职员表有哪些字段,我只能举例,可以添加例如 姓名,年龄,婚否,薪水,部门,职位,学历,邮箱,手机号,住址等等字段,假设原表没有职位这个字段,咱们来添加这个字段
alter table db_shop.staffer_bak2 add column job varchar(30) comment '职位'
4、添加主键外键
这可以根据原本的职员表哪些字段是主键和外键,咱们就设置哪些为主外键,因为你没有列出我只能猜测原表id是主键,那么设置主键sql就是alter table db_shop.staffer_bak2 add primary key(id)
假设原职员表有department_id(部门id)且与department部门表的id字段有外键约束,那么设置外键sql就是alter table db_shop.staffer_bak2 add constraint `fk1` foreign key (`department_id`) references db_shop.department(`id`)
5、删除外键约束
alter table db_shop.staffer_bak2 drop foreign key `fk1`
6、删除之前添加的职位字段
alter table db_shop.staffer_bak2 drop job
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)