mysql中的空值,NULL,空字符
Mysql數據庫是一個基於結構化數據的開源數據庫。SQL語句是MySQL數據庫中核心語言。不過在MySQL數據庫中執行SQL語句,需要小心兩個陷阱。
陷阱一:空值不一定為空
空值是一個比較特殊的字段。在MySQL數據庫中,在不同的情形下,空值往往代表不同的含義。這是MySQL數據庫的一種特性。如在普通的字段中(字符型的數據),空值就是表示空值。但是如果將一個空值的數據插入到TimesTamp類型的字段中,空值就不一定為空。此時為出現什么情況呢
我先創建了一個表。在這個表中有兩個字段:User_id(其數據類型是int)、Date(其數據類型是TimesTamp)。現在往這個表中插入一條記錄,其中往Date字段中插入的是一個NULL空值。可是當我們查詢時,其結果顯示的卻是插入記錄的當前時間。這是怎么一回事呢?其實這就是在MySQL數據庫中執行SQL語句時經常會遇到的一個陷阱:空值不一定為空。在操作時,明明插入的是一個空值的數據,但是最后查詢得到的卻不是一個空值。
在MySQL數據庫中,NULL對於一些特殊類型的列來說,其代表了一種特殊的含義,而不僅僅是一個空值。對於這些特殊類型的列,各位讀者主要是要記住兩個。一個就是筆者上面舉的TimesTamp數據類型。如果往這個數據類型的列中插入Null值,則其代表的就是系統的當前時間。另外一個是具有auto_increment屬性的列。如果往這屬性的列中插入Null值的話,則系統會插入一個正整數序列。而如果在其他數據類型中,如字符型數據的列中插入Null的數據,則其插入的就是一個空值。
陷阱二:空值不一定等於空字符
在MySQL中,空值(Null)與空字符(’’)相同嗎?答案是否定的。
在同一個數據庫表中,同時插入一個Null值的數據和一個’’空字符的數據,然后利用Select語句進行查詢。顯然其顯示的結果是不相同的。從這個結果中就可以看出,空值不等於空字符。這就是在MySQL中執行SQL語句遇到的第二個陷阱。在實際工作中,空值數據與空字符往往表示不同的含義。數據庫管理員可以根據實際的需要來進行選擇。如對於電話號碼等字段,可以默認設置為空值(表示根本不知道對方的電話號碼)或者設置為空字符(表示后來取消了這個號碼)等等。由於他們在數據庫中會有不同的表現形式,所以數據庫管理員需要區別對待。筆者更加喜歡使用空值,而不是空字符。這主要是因為針對空值這個數據類型有幾個比較特殊的運算字符。如果某個字段是空字符,數據庫中是利用字段名稱來代替。相反,如果插入的是空值,則直接顯示的是NULL。這跟其他數據庫的顯示方式也是不同的。
一是IS NULL 和IS NOT NULL關鍵字。如果要判斷某個字段是否含用空值的數據,需要使用特殊的關鍵字。其中前者表示這個字段為空,后者表示這個字段為非空。在Select語句的查詢條件中這兩個關鍵字非常的有用。如需要查詢所有電話號碼為空的用戶(需要他們補充電話號碼信息),就可以在查詢條件中加入is not null關鍵字。
二是Count等統計函數,在空值上也有特殊的應用。如現在需要統計用戶信息表中有電話號碼的用戶數量,此時就可以使用count函數、同時將電話號碼作為參數來使用。因為在統計過程中,這個函數會自動忽略空值的數據。此時統計出來的就是有電話號碼的用戶信息。如果采用的是空字符的數據,則這個函數會將其統計進去。統計剛才建立的兩條記錄時,系統統計的結果是1,而不是2。可見系統自動將Null值的數據忽略掉了。
判斷NULL用is null 或者 is not null。 sql語句里可以用ifnull函數來處理
判斷空字符串‘’,要用 ='' 或者 <>''。sql語句里可以用if(col,col,0)處理,即:當col為true時(非null,及非'')顯示,否則打印0
平時我們在使用MySQL的時候,對於MySQL中的NULL值和空值區別不能很好的理解。注意到NULL值是未知的,且占用空間,不走索引,DBA建議建表的時候最好設置字段是NOT NULL 來避免這種低效率的事情的發生。
問題 1: 首先,我們需要搞清楚 "空值" 和"NULL"的概念:
1:空值('')是不占用空間的
2: MySQL中的NULL其實是占用空間的。官方文檔說明:
“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”
長度驗證:注意空值的''之間是沒有空格的。
mysql> select length(''),length(null),length(' ');
+------------+--------------+--------------+
| length('') | length(null) | length(' ') |
+------------+--------------+--------------+
| 0 | NULL | 2 |
+------------+--------------+--------------+
問題2:
判斷字段不為空的時候,查詢語句到底是用 select * from tablename where columnname <> '' 還是用
select * from tablename where column is not null,2個查詢語句有啥不同。
eg:
mysql> show create table testaa;
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| testaa | CREATE TABLE `testaa` (
`a` int(11) NOT NULL,
`b` varchar(20) DEFAULT NULL,
`c` varchar(20) NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
插入測試數據:
mysql> insert testaa values (1,'aa','');
Query OK, 1 row affected (0.00 sec)
mysql> insert testaa values (2,'','');
Query OK, 1 row affected (0.00 sec)
mysql> insert testaa values (3,null,'');
Query OK, 1 row affected (0.00 sec)
mysql> insert testaa values (4,NULL,'');
Query OK, 1 row affected (0.00 sec)
mysql> insert testaa values (5,'aafa','fa');
Query OK, 1 row affected (0.00 sec)
mysql> insert testaa values (6,'',NULL);
ERROR 1048 (23000): Column 'c' cannot be null
mysql> select * from testaa;
+---+------+----+
| a | b | c |
+---+------+----+
| 1 | aa | |
| 2 | | |
| 3 | NULL | |
| 4 | NULL | |
| 5 | aafa | fa |
+---+------+----+
查詢驗證過程:
mysql> select * from testaa where c is not null;
+---+------+----+
| a | b | c |
+---+------+----+
| 1 | aa | |
| 2 | | |
| 3 | NULL | |
| 4 | NULL | |
| 5 | aafa | fa |
+---+------+----+
5 rows in set (0.00 sec)
mysql> select * from testaa where c <> '';
+---+------+----+
| a | b | c |
+---+------+----+
| 5 | aafa | fa |
+---+------+----+
1 row in set (0.00 sec)
mysql> select * from testaa where c = '';
+---+------+---+
| a | b | c |
+---+------+---+
| 1 | aa | |
| 2 | | |
| 3 | NULL | |
| 4 | NULL | |
+---+------+---+
4 rows in set (0.00 sec)
mysql> select * from testaa where c is null;
Empty set (0.00 sec)
mysql> select * from testaa where b is not null;
+---+------+----+
| a | b | c |
+---+------+----+
| 1 | aa | |
| 2 | | |
| 5 | aafa | fa |
+---+------+----+
3 rows in set (0.00 sec)
mysql> select * from testaa where b <> '';
+---+------+----+
| a | b | c |
+---+------+----+
| 1 | aa | |
| 5 | aafa | fa |
+---+------+----+
2 rows in set (0.00 sec)
mysql> select * from testaa where b ='';
+---+------+---+
| a | b | c |
+---+------+---+
| 2 | | |
+---+------+---+
1 row in set (0.00 sec)
mysql> select * from testaa where b is null;
+---+------+---+
| a | b | c |
+---+------+---+
| 3 | NULL | |
| 4 | NULL | |
+---+------+---+
mysql> select length(b),length(c) from testaa;
+-----------+-----------+
| length(b) | length(c) |
+-----------+-----------+
| 2 | 0 |
| 0 | 0 |
| NULL | 0 |
| NULL | 0 |
| 4 | 2 |
+-----------+-----------+
5 rows in set (0.00 sec)
mysql> select count(b),count(c) from testaa;
+----------+----------+
| count(b) | count(c) |
+----------+----------+
| 3 | 5 |
+----------+----------+
1 row in set (0.00 sec)
mysql> create table testbb ( a int primary key , b timestamp);
Query OK, 0 rows affected (0.07 sec)
mysql> show create table testbb;
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| testbb | CREATE TABLE `testbb` (
`a` int(11) NOT NULL,
`b` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
mysql> insert into testbb vales (1,null) ;
mysql> insert into testbb values (2,'');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 'b' at row 1 |
+---------+------+----------------------------------------+
mysql> select * from testbb;
+---+---------------------+
| a | b |
+---+---------------------+
| 1 | 2014-08-15 14:32:10 |
| 2 | 0000-00-00 00:00:00 |
+---+---------------------+
2 rows in set (0.00 sec)
注意事項:
1:在進行count()統計某列的記錄數的時候,如果采用的NULL值,會別系統自動忽略掉,但是空值是會進行統計到其中的。
2: 判斷NULL 用IS NULL 或者 is not null,SQL 語句函數中可以使用ifnull()函數來進行處理,判斷空字符用=''或者 <>''來進行處理
3: 對於MySQL特殊的注意事項,對於timestamp數據類型,如果往這個數據類型插入的列插入NULL值,則出現的值是當前系統時間。插入空值,則會出現 '0000-00-00 00:00:00'
4:對於空值的判斷到底是使用is null 還是 =''要根據實際業務來進行區分。
sql中,insert into與update語句,字符串 要單引號括起