MySQL中NULL與空字符串


一些剛剛接觸MySQL的孩子,經常會錯誤的認為NULL與空字符串’  ’是相同的。這看似是一件不重要的事情,但是在MySQL中,這兩者是完全不同的。NULL是指沒有值,而”則表示值是存在的,只不過是個空值。對於SQL的新手,NULL值的概念常常會造成混淆,他們常認為NULL與MySQL空字符串是相同的事。情況並非如此。例如,下述語句是完全不同的:MySQL> INSERT INTO my_table (phone) VALUES (NULL);

    mysql> INSERT INTO my_table (phone) VALUES ('');  
    這兩條語句均會將值插入phone(電話)列,但第1條語句插入的是NULL值,第2條語句插入的是空字符串。第1種情況的含義可被解釋為“電話號碼未知”,而第2種情況的含義可被解釋為“該人員沒有電話,因此沒有電話號碼”。

   為了進行NULL處理,可使用IS NULL和IS NOT NULL操作符以及IFNULL()函數。

   對於聚合(累計)函數,如COUNT()、MIN()和SUM(),將忽略NULL值。對此的例外是COUNT(*),它將計數行而不是單獨的列值。例如,下述語句產生兩個計數。首先計數表中的行數,其次計數age列中的非NULL值數目:mysql> SELECT COUNT(*), COUNT(age) FROM person;  
對於某些列類型,MySQL將對NULL值進行特殊處理。如果將NULL插入TIMESTAMP列,將插入當前日期和時間。如果將NULL插入具有AUTO_INCREMENT屬性的整數列,將插入序列中的下一個編號。另外''可以走索引,null走不了索引


MySQL的null與空字符串:

搞過Oracle的人,常常會對MySQL的null與空字符串''搞錯。
在Oracle里:null 與 ''是等價的。

15:02:40 sql>create table test(v varchar2(10));
15:02:46 sql>insert into test values('');
15:03:07 sql>insert into test values(null);
15:03:12 sql>commit;
15:04:05 sql>select count(1) from test where v is null;
 COUNT(1)
----------
         2
15:04:07 sql>select count(1) from test where v ='';
  COUNT(1)
----------
         0  

15:04:41 sql>select count(1) from test where v <>'';
  COUNT(1)
----------
         0         
注意:Oracle中null僅只能參與is null 和 is not null運算。如何使用 <> 、= 與null進行比較,都會返回false。        

但在MySQL里,null與 ''是完全不同的:NULL是指沒有值,而''則表示值是存在的,只不過是個空值。

見如下實驗:
mysql> create table test (v varchar(10));
ERROR 1050 (42S01): Table 'test' already exists
mysql> drop table test;
Query OK, 0 rows affected (0.11 sec)

mysql> create table test (v varchar(10));
Query OK, 0 rows affected (0.11 sec)

mysql> insert into test values(null);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test values('');
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+
| v    |
+------+
| NULL |
|      |
+------+
2 rows in set (0.00 sec)

mysql> select count(1) from test where v is null;
+----------+
| count(1) |
+----------+
|        1 |
+----------+
1 row in set (0.04 sec)

mysql> select count(1) from test where v = '';
+----------+
| count(1) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)


再看看MySQL在時間類型字段上是如何處理null與''

mysql> create table t_date (d timestamp);
ERROR 1050 (42S01): Table 't_date' already exists
mysql> drop table t_date;
Query OK, 0 rows affected (0.12 sec)

mysql> create table t_date (d timestamp ,d2 datetime);
Query OK, 0 rows affected (0.14 sec)

mysql> insert into t_date values(null,null);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t_date;
+---------------------+------+
| d                   | d2   |
+---------------------+------+
| 2014-02-19 15:42:11 | NULL |
+---------------------+------+
1 row in set (0.00 sec)

注:timestamp類型插入null,卻插入了系統當前時間

mysql> desc t_date;
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type      | Null | Key | Default           | Extra                       |
+-------+-----------+------+-----+-------------------+-----------------------------+
| d     | timestamp | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| d2    | datetime  | YES  |     | NULL              |                             |
+-------+-----------+------+-----+-------------------+-----------------------------+

原來MySQL給自動給timestamp類型增加了默認值而不能為null。

mysql> insert into t_date (d) values ('');
ERROR 1292 (22007): Incorrect datetime value: '' for column 'd' at row 1
mysql> insert into t_date (d2) values ('');
ERROR 1292 (22007): Incorrect datetime value: '' for column 'd2' at row 1
時間字段不能插入''。

mysql> select @@version;
+------------------+
| @@version        |
+------------------+
| 5.6.14-ndb-7.3.3 |
+------------------+
1 row in set (0.00 sec)

不同版本的MySQL對時間字段的處理不一樣,有的版本會把''轉換為'0000-00-00 00:00:00'插入到表中。

而且相同版本不同的命令也可能不一樣。

在我的實驗中,使用load data 導入文本文件時,就發生了''轉換為'0000-00-00 00:00:00'保存到表中。

附:
  使用load data進行導入數據的時候,沒有數據的字段插入的不是null,而是'';為了能插入null,在文本文件中使用'\N'來代表null。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM