mysql中的null字段值的处理及大小写问题

时间:2023-03-08 20:30:32
mysql中的null字段值的处理及大小写问题

在MySQL中,NULL字段的处理,需要注意,当在处理查询条件中有NULL,很有可能你得到的值不是想要的,因为,在MySQL中,判断NULL值相等(=)或者不等(!=)都会返回false。主要出现在常见的SELECT以及WHERE字句中。

为了处理这种特殊的情况,MySQL提供了如下的关键字进行特殊处理:

  • IS NULL: 当列的值是NULL,此运算符返回true。
  • IS NOT NULL: 当列的值不为NULL, 运算符返回true。
  • <=>: 比较操作符(不同于=运算符),当比较的的两个值为NULL时返回true。

关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。在MySQL中,NULL值与任何其它值的比较(即使是NULL)永远返回false,即 NULL = NULL 返回false 。

下面看看例子,就很清楚的理解是什么意思了。

先在test数据库中创建一个表checknull。

 mysql> use test
Database changed
mysql> show tables;
Empty set (0.00 sec) mysql> create table checknull(
-> name varchar() not null,
-> age int);
Query OK, rows affected (0.11 sec)

我们看看这个表的创建基本信息,用show和desc分别查看:

 mysql> show create table checknull;
+-----------+-------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-----------+-------------------------------------------------------------------------------------------------------------------------------+
| checknull | CREATE TABLE `checknull` (
`name` varchar() NOT NULL,
`age` int() DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+-----------+-------------------------------------------------------------------------------------------------------------------------------+
row in set (0.01 sec) mysql> desc checknull;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name | varchar() | NO | | NULL | |
| age | int() | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
rows in set (0.00 sec)

我们开始测试一下,第一步,向这个表中插入数据:

 mysql> insert checknull (name, age) values("water", );
Query OK, row affected (0.00 sec) mysql>
mysql> insert checknull (name, age) values("shihuc", NULL);
Query OK, row affected (0.00 sec) mysql>
mysql> select * from checknull;
+--------+------+
| name | age |
+--------+------+
| water | |
| shihuc | NULL |
+--------+------+
rows in set (0.00 sec)

接下来,再查询看看,先查询所有的age字段是NULL的用户信息:

 mysql> select * from checknull where age = NULL;
Empty set (0.00 sec) mysql> select * from checknull where age IS NULL;
+--------+------+
| name | age |
+--------+------+
| shihuc | NULL |
+--------+------+
row in set (0.00 sec)
 mysql> select * from checknull where age != NULL;
Empty set (0.00 sec) mysql> select * from checknull where age IS NOT NULL;
+-------+------+
| name | age |
+-------+------+
| water | |
+-------+------+
row in set (0.00 sec)

是不是发现,结果不同?那么我现在,通过修改大小写来查看查询结果:

 mysql> select * from checknull where age IS null;
+--------+------+
| name | age |
+--------+------+
| shihuc | NULL |
+--------+------+
row in set (0.00 sec) mysql> select * from checknull where age = null;
Empty set (0.00 sec)
 mysql> select * from checknull where age != null;
Empty set (0.00 sec) mysql> select * from checknull where age is not null;
+-------+------+
| name | age |
+-------+------+
| water | |
+-------+------+
row in set (0.00 sec)

发现结果和上面的日志反映的内容一样。

这里补充一个小tips,那就是在Linux下,mysql默认情况下,数据库的名字,表的名字和字段的名字是区分大小写的,但是字段的值是不区分大小写的。表的名字和字段的名字是否区分大小写,可以查看数据库变量lower_case_table_names的值,0表示区分大小写;1表示不区分,统一按照小写对待。

 mysql> show variables like "%case%";
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| lower_case_file_system | OFF |
| lower_case_table_names | |
+------------------------+-------+
rows in set (0.00 sec)

而对于字段的值,想要区分大小写,可以使用BINARY加以限制。不管是在创建表的时候,还是在查询的条件字句中都可以使用。

 mysql> create table lowupper(
-> name varchar() not null,
-> age int,
-> home varchar() binary);
Query OK, rows affected (0.10 sec) mysql> show create table lowupper;
+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| lowupper | CREATE TABLE `lowupper` (
`name` varchar() NOT NULL,
`age` int() DEFAULT NULL,
`home` varchar() CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
row in set (0.00 sec)

上面日志中,可以看到,创建表的时候,在home字段后面加了约束binary,通过show可以看到,home字段有一个校对规则 latin1_bin,说明,这个会在插入/查询数据的时候是区分大小写的。

下面插入数据做些验证:

 mysql> insert lowupper (name, age, home) values ("shihuc", , "Beijing, china");
Query OK, row affected (0.00 sec) mysql>
mysql> insert lowupper (name, age, home) values ("water", , "BEIJING, china");
Query OK, row affected (0.00 sec) mysql> insert lowupper (name, age, home) values ("xiaocheng", , "hubei");
Query OK, row affected (0.00 sec) mysql> insert lowupper (name, age, home) values ("zhangsan", null, "china");
Query OK, row affected (0.00 sec) mysql> insert lowupper (name, age, home) values ("lisi", null, "CHINA");
Query OK, row affected (0.00 sec) mysql> insert lowupper (name, age, home) values ("wangwu", null, "China");
Query OK, row affected (0.00 sec) mysql> select * from lowupper;
+-----------+------+----------------+
| name | age | home |
+-----------+------+----------------+
| shihuc | | Beijing, china |
| water | | BEIJING, china |
| xiaocheng | | hubei |
| zhangsan | NULL | china |
| lisi | NULL | CHINA |
| wangwu | NULL | China |
+-----------+------+----------------+
rows in set (0.00 sec)

下面,再查询一下看看,是否有区分:

 mysql> select * from lowupper where home = "china";
+----------+------+-------+
| name | age | home |
+----------+------+-------+
| zhangsan | NULL | china |
+----------+------+-------+
row in set (0.00 sec)

再操作上面checknull表,在其中插入一条新的数据,进行查询,看是否区分大小写:

 mysql> insert checknull (name, age) values ("SHIHUC", null);
Query OK, row affected (0.00 sec) mysql> select * from checknull;
+--------+------+
| name | age |
+--------+------+
| water | |
| shihuc | NULL |
| SHIHUC | NULL |
+--------+------+
rows in set (0.00 sec) mysql> select * from checknull where name = "shihuc";
+--------+------+
| name | age |
+--------+------+
| shihuc | NULL |
| SHIHUC | NULL |
+--------+------+
rows in set (0.00 sec) mysql> select * from checknull where binary name = "shihuc";
+--------+------+
| name | age |
+--------+------+
| shihuc | NULL |
+--------+------+
row in set (0.00 sec)

是不是很显然的,说明MySQL的大小写问题,还是很有意思的,需要注意,在linux环境下。windows环境下,没有测试,不是很确定。有经验的可以分享一下!