The thirteenth lecture of Mysql series elaborates on the divine pit caused by NULL, which is hard to guard against

Use NULL in comparison operators

mysql> select 1>NULL;
+--------+
| 1>NULL |
+--------+
|   NULL |
+--------+
1 row in set (0.00 sec)

mysql> select 1<NULL;
+--------+
| 1<NULL |
+--------+
|   NULL |
+--------+
1 row in set (0.00 sec)

mysql> select 1<>NULL;
+---------+
| 1<>NULL |
+---------+
|    NULL |
+---------+
1 row in set (0.00 sec)

mysql> select 1>NULL;
+--------+
| 1>NULL |
+--------+
|   NULL |
+--------+
1 row in set (0.00 sec)

mysql> select 1<NULL;
+--------+
| 1<NULL |
+--------+
|   NULL |
+--------+
1 row in set (0.00 sec)

mysql> select 1>=NULL;
+---------+
| 1>=NULL |
+---------+
|    NULL |
+---------+
1 row in set (0.00 sec)

mysql> select 1<=NULL;
+---------+
| 1<=NULL |
+---------+
|    NULL |
+---------+
1 row in set (0.00 sec)

mysql> select 1!=NULL;
+---------+
| 1!=NULL |
+---------+
|    NULL |
+---------+
1 row in set (0.00 sec)

mysql> select 1<>NULL;
+---------+
| 1<>NULL |
+---------+
|    NULL |
+---------+
1 row in set (0.00 sec)

mysql> select NULL=NULL,NULL!=NULL;
+-----------+------------+
| NULL=NULL | NULL!=NULL |
+-----------+------------+
|      NULL |       NULL |
+-----------+------------+
1 row in set (0.00 sec)

mysql> select 1 in (null),1 not in (null),null in (null),null not in (null);
+-------------+-----------------+----------------+--------------------+
| 1 in (null) | 1 not in (null) | null in (null) | null not in (null) |
+-------------+-----------------+----------------+--------------------+
|        NULL |            NULL |           NULL |               NULL |
+-------------+-----------------+----------------+--------------------+
1 row in set (0.00 sec)

mysql> select 1=any(select null),null=any(select null);
+--------------------+-----------------------+
| 1=any(select null) | null=any(select null) |
+--------------------+-----------------------+
|               NULL |                  NULL |
+--------------------+-----------------------+
1 row in set (0.00 sec)

mysql> select 1=all(select null),null=all(select null);
+--------------------+-----------------------+
| 1=all(select null) | null=all(select null) |
+--------------------+-----------------------+
|               NULL |                  NULL |
+--------------------+-----------------------+
1 row in set (0.00 sec)

Conclusion: When any value is compared with NULL using operators (>, <, >=, <=,!=, <>) or (in, not in, any/some, all), the return value is NULL, and NULL is used as When it is a boolean, it is neither 1 nor 0.

Prepare data

mysql> create table test1(a int,b int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test1 values (1,1),(1,null),(null,null);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from test1;
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
|    1 | NULL |
| NULL | NULL |
+------+------+
3 rows in set (0.00 sec)

Take a look at the above three data, especially the NULL record.

IN, NOT IN and NULL comparison

Comparison of IN and NULL

mysql> select * from test1;
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
|    1 | NULL |
| NULL | NULL |
+------+------+
3 rows in set (0.00 sec)

mysql> select * from test1 where a in (null);
Empty set (0.00 sec)

mysql> select * from test1 where a in (null,1);
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
|    1 | NULL |
+------+------+
2 rows in set (0.00 sec)

Conclusion: When IN and NULL are compared, records that are NULL cannot be queried.

NOT IN and NULL comparison

mysql> select * from test1 where a not in (1);
Empty set (0.00 sec)

mysql> select * from test1 where a not in (null);
Empty set (0.00 sec)

mysql> select * from test1 where a not in (null,2);
Empty set (0.00 sec)

mysql> select * from test1 where a not in (2);
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
|    1 | NULL |
+------+------+
2 rows in set (0.00 sec)

Conclusion: When NOT IN is followed by a NULL value, no matter what the circumstances, the entire sql query result is empty.

EXISTS, NOT EXISTS and NULL comparison

mysql> select * from test2;
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
|    1 | NULL |
| NULL | NULL |
+------+------+
3 rows in set (0.00 sec)

mysql> select * from test1 t1 where exists (select * from test2 t2 where t1.a = t2.a);
+------+------+
| a    | b    |
+------+------+
|    1 |    1 |
|    1 | NULL |
+------+------+
2 rows in set (0.00 sec)

mysql> select * from test1 t1 where not exists (select * from test2 t2 where t1.a = t2.a);
+------+------+
| a    | b    |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)

Above we copied the table test1 and created the table test2.

Use exists and not exists in the query statement to compare test1.a=test2.a, because = cannot compare NULL, and the result is consistent with expectations.

Only IS NULL and IS NOT NULL can be used to judge NULL

mysql> select 1 is not null;
+---------------+
| 1 is not null |
+---------------+
|             1 |
+---------------+
1 row in set (0.00 sec)

mysql> select 1 is null;
+-----------+
| 1 is null |
+-----------+
|         0 |
+-----------+
1 row in set (0.00 sec)

mysql> select null is null;
+--------------+
| null is null |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

mysql> select null is not null;
+------------------+
| null is not null |
+------------------+
|                0 |
+------------------+
1 row in set (0.00 sec)

Looking at the above effect, the returned result is 1 or 0.

Conclusion: Only IS NULL and IS NOT NULL can be used to judge whether it is empty.

The pit of NULL in aggregate function

Example

mysql> select count(a),count(b),count(*) from test1;
+----------+----------+----------+
| count(a) | count(b) | count(*) |
+----------+----------+----------+
|        2 |        1 |        3 |
+----------+----------+----------+
1 row in set (0.00 sec)

Count(a) returns 2 rows of records, and the a field is NULL, no statistics are obtained.

Count(b) returns 1 row of records, and the 2 rows of NULL records are not counted.

count(*) can count all data, regardless of whether the field data is NULL.

Keep watching

mysql> select * from test1 where a is null;
+------+------+
| a    | b    |
+------+------+
| NULL | NULL |
+------+------+
1 row in set (0.00 sec)

mysql> select count(a) from test1 where a is null;
+----------+
| count(a) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

The first sql above uses is null to query the result, and count(a) in the second sql returns 0 rows.

Conclusion: count (field) cannot count the value of the field as NULL, count (*) can count the rows with the value of null.

NULL cannot be used as the value of the primary key

mysql> create table test3(a int primary key,b int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test3 values (null,1);
ERROR 1048 (23000): Column 'a' cannot be null

Above we created a table test3, the field a is not specified and cannot be empty, and a NULL data is inserted. The reason for the error: the value of the a field cannot be NULL. Let's look at the table creation statement:

mysql> show create table test3;
+-------+------------+
| Table | Create Table      |
+-------+------------+
| test3 | CREATE TABLE `test3` (
  `a` int(11) NOT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
+-------+------------+
1 row in set (0.00 sec)

As can be seen from the above script, when the field is the primary key, the field will be automatically set to not null.

Conclusion: When the field is the primary key, the field will be automatically set to not null.

After reading the above, it is quite dizzy. The NULL situation is indeed more difficult to handle and error-prone. The most effective way is to avoid using NULL. Therefore, it is strongly recommended that the field is not allowed to be NULL when creating a field and set a default value.

to sum up

  • When NULL is used as a boolean, it is neither 1 nor 0

  • Any value and NULL use operators (>, <, >=, <=, !=, <>) or (in, not in, any/some, all), the return value is NULL

  • When IN and NULL are compared, records that are NULL cannot be queried

  • When there is a NULL value after NOT IN, no matter what the case, the entire SQL query result is empty

  • To judge whether it is empty, only IS NULL, IS NOT NULL can be used

  • count(field) cannot count the value of the field as NULL, count(*) can count the row with the value of null

  • When the field is the primary key, the field will be automatically set to not null

  • The pit caused by NULL is hard to guard against. It is strongly recommended that the field is not allowed to be NULL when creating a field, and give a default value

Guess you like

Origin blog.csdn.net/m0_47157676/article/details/108703649