1. 程式人生 > >mysql從頭學一 1.0資料型別-日期型別

mysql從頭學一 1.0資料型別-日期型別

日期時間型別

MySQL 中有多種資料型別可以用於日期和時間的表示,不同的版本可能有所差異,表 3-2 中列出了 MySQL 5.0 中所支援的日期和時間型別。表 3-2     MySQL 中的日期和時間型別

日期和時間型別

 位元組

最小值

最大值

DATE

4

1000-01-01

9999-12-31

DATETIME          

8

1000-01-01 00:00:00

9999-12-31 23:59:59

TIMESTAMP

4

19700101080001

2038 年的某個時刻

TIME

3

-838:59:59

838:59:59

YEAR

1

1901

2155

 

這些資料型別的主要區別如下: l 如果要用來表示年月日,通常用 DATE 來表示。

  1. 如果要用來表示年月日時分秒,通常用 DATETIME 表示。
  2. 如果只用來表示時分秒,通常用 TIME 來表示。
  3. 如果需要經常插入或者更新日期為當前系統時間,則通常使用 TIMESTAMP 來表示。

TIMESTAMP 值返回後顯示為“YYYY-MM-DD HH:MM:SS”格式的字串,顯示寬度固定為 19 個字元。如果想要獲得數字值,應在 TIMESTAMP 列新增+0。

  1. 如果只是表示年份,可以用 YEAR 來表示,它比 DATE 佔用更少的空間。YEAR 有 2 位或 4 位格式的年。預設是 4 位格式。在 4 位格式中,允許的值是 1901~2155 和 0000。在 2 位格式中,允許的值是 70~69,表示從 1970~2069 年。MySQL 以 YYYY 格式顯示 YEAR 值。

 

 從表 3-2 中可以看出,每種日期時間型別都有一個有效值範圍,如果超出這個範圍,在預設的 SQLMode 下,系統會進行錯誤提示,並將以零值來進行儲存。不同日期型別零值的表示如表 3-3 所示。

表 3-3                                          MySQL 中日期和時間型別的零值表示

資料型別

零值表示

DATETIME

0000-00-00 00:00:00

DATE

0000-00-00

TIMESTAMP

00000000000000

TIME

00:00:00

YEAR

0000

    DATE、TIME 和 DATETIME 是最常使用的 3 種日期型別,以下例子在 3 種類型欄位插入了相同的日期值,來看看它們的顯示結果:

        首先建立表 t,欄位分別為 date、time、datetime 三種日期型別:

mysql> create table t (d date,t time,dt datetime);

Query OK, 0 rows affected (0.01 sec)

 mysql> desc t;

+-------+----------+------+-----+---------+-------+

| Field | Type     | Null | Key | Default | Extra |

+-------+----------+------+-----+---------+-------+

| d     | date     | YES  |     | NULL    |       |

| t     | time     | YES  |     | NULL    |       |

| dt    | datetime | YES  |     | NULL    |       |

+-------+----------+------+-----+---------+-------+

3 rows in set (0.01 sec)

 

用 now()函式插入當前日期:

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

 

檢視顯示結果:

mysql> select * from t;

 

    顯而易見,DATETIME是DATE和TIME的組合,使用者可以根據不同的需要,來選擇不同的日期或時間型別以滿足不同的應用。

    TIMESTAMP也用來表示日期,但是和DATETIME有所不同,後面的章節中會專門介紹。下例對TIMESTAMP型別的特性進行一些測試。      建立測試表t,欄位id1為TIMESTAMP型別:

mysql> create table t (id1 timestamp); Query OK, 0 rows affected (0.03 sec) mysql> desc t;

+-------+-----------+------+-----+-------------------+-------+

| Field | Type      | Null | Key | Default           | Extra |

+-------+-----------+------+-----+-------------------+-------+

| id2   | timestamp | YES  |     | CURRENT_TIMESTAMP |       |

+-------+-----------+------+-----+-------------------+-------+

1 row in set (0.00 sec)

可以發現,系統給 tm 自動建立了預設值 CURRENT_TIMESTAMP(系統日期)。插入一個 NULL 值試試:

mysql> insert into t values(null);

Query OK, 1 row affected (0.00 sec)         mysql> select * from t;

+---------------------+

| t                   |

+---------------------+

| 2007-07-04 16:37:24 |

+---------------------+

1 row in set (0.00 sec)

    果然,t中正確插入了系統日期。注意,MySQL只給表中的第一個TIMESTAMP欄位設定預設值為系統日期,如果有第二個TIMESTAMP型別,則預設值設定為0值,測試如下:

mysql> alter table t add id2 timestamp; Query OK, 0 rows affected (0.03 sec)

Records: 0  Duplicates: 0  Warnings: 0

 mysql> show create table t \G;

*************************** 1. row ***************************

       Table: t

Create Table: CREATE TABLE `t` (

  `id1` timestamp NOT NULL default CURRENT_TIMESTAMP,

  `id2` timestamp NOT NULL default '0000-00-00 00:00:00'

) ENGINE=MyISAM DEFAULT CHARSET=gbk

1 row in set (0.00 sec))

    當然,可以修改id2的預設值為其他常量日期,但是不能再修改為current_timestmap,因為MySQL規定TIMESTAMP型別欄位只能有一列的預設值為current_timestmap,如果強制修改,系統會報如下錯誤提示:

mysql> alter table t modify id2 timestamp default current_timestamp;

ERROR 1293 (HY000): Incorrect table definition; there can be only one TIMESTAMP column with

CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

    TIMESTAMP還有一個重要特點,就是和時區相關。當插入日期時,會先轉換為本地時區後存放;而從資料庫裡面取出時,也同樣需要將日期轉換為本地時區後顯示。這樣,兩個不同時區的使用者看到的同一個日期可能是不一樣的,下面的例子演示了這個差別。

  1. 建立表t8,包含欄位id1(TIMESTAMP)和id2(DATETIME),設定id2的目的是為了和id1做對比:

CREATE TABLE `t8` (

  `id1` timestamp NOT NULL default CURRENT_TIMESTAMP,

  `id2` datetime default NULL

)

Query OK, 0 rows affected (0.03 sec)

  1. 檢視當前時區:

mysql> show variables like 'time_zone';

+---------------+--------+

| Variable_name | Value  |

+---------------+--------+

| time_zone     | SYSTEM | 

+---------------+--------+

    1. row in set (0.00 sec)

可以發現,時區的值為“SYSTEM”,這個值預設是和主機的時區值一致的,因為我們在中國,這裡的“SYSTEM”實際是東八區(+8:00)。

  1. 用 now()函式插入當前日期:

mysql> select * from t8;

+---------------------+---------------------+

| id1                 | id2                 |

+---------------------+---------------------+

| 2007-09-25 17:26:50 | 2007-09-25 17:26:50 | 

+---------------------+---------------------+

    1. row in set (0.01 sec)

結果顯示 id1 和 id2 的值完全相同。(4)修改時區為東九區,再次查看錶中日期:

mysql> set time_zone='+9:00';

Query OK, 0 rows affected (0.00 sec)

 mysql> select * from t8;

+---------------------+---------------------+

| id1                 | id2                 |

+---------------------+---------------------+

| 2007-09-25 18:26:50 | 2007-09-25 17:26:50 | 

+---------------------+---------------------+

1 row in set (0.00 sec)

結果中可以發現,id1的值比 id2的值快了 1個小時,也就是說,東九區的人看到的“2007-09-25 18:26:50”是當地時區的實際日期,也就是東八區的“2007-09-25 17:26:50”,如果還是以 “2007-09-25 17:26:50”理解時間必然導致誤差。

    TIMESTAMP的取值範圍為19700101080001到2038年的某一天,因此它不適合存放比較久遠的日期,下面簡單測試一些這個範圍:

mysql> insert into t values (19700101080001);

Query OK, 1 row affected (0.00 sec)

 

mysql> select * from t; +---------------------+

| t                   |

+---------------------+

| 1970-01-01 08:00:01 |

+---------------------+

1 row in set (0.00 sec)

 mysql> insert into t values (19700101080000); Query OK, 1 row affected, 1 warning (0.00 sec)

 

其中 19700101080000 超出了 tm 的下限,系統出現警告提示。查詢一下,發現插入值變成了 0 值。

mysql> select * from t; +---------------------+

| t                   |

+---------------------+

| 1970-01-01 08:00:01 |

| 0000-00-00 00:00:00 |

+---------------------+

2 rows in set (0.00 sec)

 

再來測試一下 TIMESTAMP 的上限值:

mysql> insert into t values('2038-01-19 11:14:07'); Query OK, 1 row affected (0.00 sec)

 mysql> select * from t;

+---------------------+

| t                   |

+---------------------+

| 2038-01-19 11:14:07 |

+---------------------+

  1. row in set (0.00 sec)

 

mysql> insert into t values('2038-01-19 11:14:08');

Query OK, 1 row affected, 1 warning (0.00 sec)

 mysql> select * from t; +---------------------+

| t                   |

+---------------------+

| 2038-01-19 11:14:07 |

| 0000-00-00 00:00:00 |

+---------------------+

  1. rows in set (0.00 sec)

 從上面例子可以看出,TIMESTAMP和DATETIME的表示方法非常類似,區別主要有以下幾點。

  1. TIMESTAMP支援的時間範圍較小,其取值範圍從19700101080001到2038年的某個時間,而DATETIME是從1000-01-01 00:00:00到9999-12-31 23:59:59,範圍更大。
  2. 表中的第一個TIMESTAMP列自動設定為系統時間。如果在一個TIMESTAMP列中插入

NULL,則該列值將自動設定為當前的日期和時間。在插入或更新一行但不明確給 TIMESTAMP列賦值時也會自動設定該列的值為當前的日期和時間,當插入的值超出取值範圍時,MySQL認為該值溢位,使用“0000-00-00 00:00:00”進行填補。

  1. TIMESTAMP的插入和查詢都受當地時區的影響,更能反應出實際的日期。而

DATETIME則只能反應出插入時當地的時區,其他時區的人檢視資料必然會有誤差的。

  1. TIMESTAMP的屬性受MySQL版本和伺服器SQLMode的影響很大,本章都是以MySQL

5.0為例進行介紹,在不同的版本下可以參考相應的MySQL幫助文件。

 

YEAR 型別主要用來表示年份,當應用只需要記錄年份時,用 YEAR 比 DATE 將更節省空間。

下面的例子在表 t 中定義了一個 YEAR 型別欄位,並插入一條記錄:

mysql> create table t(y year);

Query OK, 0 rows affected (0.01 sec)

 mysql> desc t;

+-------+---------+------+-----+---------+-------+

| Field | Type    | Null | Key | Default | Extra |

+-------+---------+------+-----+---------+-------+

| y     | year(4) | YES  |     | NULL    |       |

+-------+---------+------+-----+---------+-------+

1 row in set (0.00 sec)

 

mysql> insert into t values(2100);

Query OK, 1 row affected (0.00 sec)

 mysql> select * from t;

+------+

| y    |

+------+

| 2100 |

+------+

1 row in set (0.00 sec)

    MySQL 以 YYYY 格式檢索和顯示 YEAR 值,範圍是 1901~2155。當使用兩位字串表示年份時,其範圍為“00”到“99”。

  1. “00”到“69”範圍的值被轉換為 2000~2069 範圍的 YEAR 值
  2. “70”到“99”範圍的值被轉換為 1970~1999 範圍的 YEAR 值。

細心的讀者可能發現,在上面的例子中,日期型別的插入格式有很多,包括整數(如 2100)、字串(如 2038-01-19 11:14:08)、函式(如 NOW())等,大家可能會感到疑惑,到

底什麼樣的格式才能夠正確地插入到對應的日期欄位中呢?下面以 DATETIME 為例進行介紹。

  1. YYYY-MM-DD HH:MM:SS 或 YY-MM-DD HH:MM:SS 格式的字串。允許“不嚴格”

語法:任何標點符都可以用做日期部分或時間部分之間的間割符。例如,“98-12-31 11:30:45”、“98.12.31 11+30+45”、“98/12/31 11*30*45”和“[email protected]@31 11^30^45” 是等價的。對於包括日期部分間割符的字串值,如果日和月的值小於 10,不需要指定兩位數。“1979-6-9”與“1979-06-09”是相同的。同樣,對於包括時間部分間割符的字串值,如果時、分和秒的值小於 10,不需要指定兩位數。“1979-10-30

1:2:3”與“1979-10-30 01:02:03”相同。

  1. YYYYMMDDHHMMSS 或 YYMMDDHHMMSS 格式的沒有間割符的字串,假定字串對於日期型別是有意義的。例如,“19970523091528”和“970523091528”被解釋為“1997-05-23 09:15:28”,但“971122129015”是不合法的(它有一個沒有意義的分鐘部分),將變為“0000-00-00 00:00:00”。
  2. YYYYMMDDHHMMSS 或 YYMMDDHHMMSS 格式的數字,假定數字對於日期型別是有意義的。例如,19830905132800和830905132800被解釋為“1983-09-05 13:28:00”。

數字值應為 6、8、12 或者 14 位長。如果一個數值是 8 或 14 位長,則假定為 YYYYMMDD 或 YYYYMMDDHHMMSS 格式,前 4 位數表示年。如果數字 是 6 或 12 位長,則假定為 YYMMDD 或 YYMMDDHHMMSS 格式,前 2 位數表示年。其他數字被解釋為彷彿用零填充到了最近的長度。

  1. 函式返回的結果,其值適合 DATETIME、DATE 或者 TIMESTAMP 上下文,例如 NOW() 或 CURRENT_DATE。

對於其他資料型別,其使用原則與上面的內容類似,限於篇幅,這裡就不再贅述。

最後通過一個例子,說明如何採用不同的格式將日期“2007-9-3 12:10:10”插入到 DATETIME 列中。

mysql> create table t6(dt datetime); Query OK, 0 rows affected (0.03 sec)

 

mysql> insert into t6 values('2007-9-3 12:10:10');

Query OK, 1 row affected (0.00 sec)

 

mysql> insert into t6 values('2007/9/3 12+10+10');

Query OK, 1 row affected (0.00 sec)

 

mysql> insert into t6 values('20070903121010'); Query OK, 1 row affected (0.01 sec)

 

mysql> insert into t6 values(20070903121010);

Query OK, 1 row affected (0.00 sec)

 

mysql> select * from t6; +---------------------+

| dt                  |

+---------------------+

| 2007-09-03 12:10:10 | 

| 2007-09-03 12:10:10 | 

| 2007-09-03 12:10:10 | 

| 2007-09-03 12:10:10 |  +---------------------+

4 rows in set (0.00 sec)