|
· “零”值是特殊值,但你可以使用表內顯示的值明確保存或引用它們。你也可以使用值'0'或0來保存或引用,寫起來更容易。
· MyODBC中使用的「零」日期或時間值在MyODBC 2.50.12及以上版本中會自動轉換為NULL,因為ODBC不能處理此類值。
1. DATETIME、DATE和TIMESTAMP類型
DATETIME、DATE和TIMESTAMP類型是相關的。該節描述了它們的特徵,它們的相似點和不同點。
當你需要同時包含日期和時間資訊的值時則使用DATETIME類型。 MySQL以'YYYY-MM-DD HH:MM:SS'格式擷取並顯示DATETIME值。支援的範圍為'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。 (「支持」表示儘管先前的值可能工作,但沒有保證)。
當你只需要日期值而不需要時間部分時應使用DATE類型。 MySQL用'YYYY-MM-DD'格式擷取並顯示DATE值。支援的範圍是'1000-01-01'到 '9999-12-31'。
TIMESTAMP欄位類型的屬性不固定,取決於MySQL版本和伺服器運行的SQL模式。這些屬性將在本節後面描述。
可以使用任何常見格式指定DATETIME、DATE和TIMESTAMP值:
· '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'和'98@12@31 11^30^45 '是等價的。
· 'YYYY-MM-DD'或'YY-MM-DD'格式的字串。這裡也允許使用「不嚴格的」語法。例如,'98-12-31'、'98.12.31'、'98/12/31'和'98@12@31'是等價的。
· 'YYYYMMDDHHMMSS'或'YYMMDDHHMMSS'格式的沒有間割符的字串,假定字串對於日期類型是有意義的。例如,'19970523091528'和'970523091528'被解釋為'1997-05-23 09:15:28',但'971122129015'是不合法的(它有一個沒有意義的分鐘部分),將變為' 00-00 00:00:00'。
· 'YYYYMMDD'或'YYMMDD'格式的沒有間割符的字串,假定字串對於日期類型是有意義的。例如,'19970523'和'970523'被解釋為 '1997-05-23',但'971332'是不合法的(它有一個沒有意義的月和日部分),將變為'0000-00-00 '。
· YYYYMMDDHHMMSS或YYMMDDHHMMSS格式的數字,假設數字對於日期類型是有意義的。例如,19830905132800和830905132800被解釋為 '1983-09-05 13:28:00'。
· YYYYMMDD或YYMMDD格式的數字,假設數字對於日期類型是有意義的。例如,19830905和830905被解釋為'1983-09-05'。
· 函數傳回的結果,其值適合DATETIME、DATE或TIMESTAMP上下文,例如NOW()或CURRENT_DATE。
無效DATETIME、DATE或TIMESTAMP值轉換為對應類型的「零」值('0000-00-00 00:00:00'、'0000-00-00'或000000000000000)。
對於包含日期部分間割符的字串值,如果日和月的值小於10,則不需要指定兩位數。 '1979-6-9'與'1979-06-09'是相同的。同樣,對於包含時間部分間割符的字串值,如果時、分和秒的值小於10,則不需要指定兩位數。 '1979-10-30 1:2:3'與'1979-10-30 01:02:03'相同。
數字值應為6、8、12或14位長。若一個數值是8或14位長,則假定為YYYYMMDD或YYYYMMDDHHMMSS格式,前4位數表示年。若數字 是6或12位長,則假定為YYMMDD或YYMMDDHHMMSS格式,前2位數表示年。其它數字被解釋為彷彿用零填充到了最近的長度。
指定為非限定符字串的值使用給定的長度進行解釋。如果字串為8或14字元長,前4位數表示年。否則,前2位數表示年。從左向右解釋字串內出現的各部分,以發現年、月、日、小時、分和秒值。這說明不應使用少於6字元的字串。例如,如果你指定'9903',認為它表示1999年3月,MySQL將在你的表內插入一個「零」日期值。這是因為年和月值是99和03,但日部分完全遺失,因此該值不是一個合法的日期。但是,可以明顯指定一個零值來代表缺少的月或日部分。例如,可以使用'990300'來插入值'1999-03-00'。
在一定程度上,可以將一個日期類型的值分配給一個不同的日期類型。但是,值可能會更改或丟失一些資訊:
· 如果你為一個DATETIME或TIMESTAMP物件分配一個DATE值,結果值的時間部分被設定為'00:00:00',因為DATE值未包含時間信息。
· 如果你為一個DATE物件指派一個DATETIME或TIMESTAMP值,結果值的時間部分被刪除,因為DATE值未包含時間資訊。
· 記住儘管可以使用相同的格式指定DATETIME、DATE和TIMESTAMP值,不同類型的值的範圍卻不同。例如,TIMESTAMP值不能早於1970或晚於2037。這說明一個日期,例如'1968-01-01',雖然對於DATETIME或DATE值是有效的,但對於TIMESTAMP值卻無效,如果分配給這樣一個物件將被轉換為0。
當指定日期值時請注意某些缺陷:
· 指定為字串的值允許的非嚴格格式可能會欺騙。例如,值'10:11:12'由於‘:’間割符看上去可能像時間值,但如果用於日期上下文值則被解釋為年'2010-11-12'。值'10:45:15'被轉換為'0000-00-00'因為'45'不是合法月。
· 在非嚴格模式,MySQL伺服器只對日期的合法性進行基本檢查:年、月和日的範圍分別是1000到9999、00到12和00到31。任何包含超出這些範圍的部分的日期被轉換成'0000-00-00'。請注意仍然允許你保存非法日期,例如'2002-04-31'。要確保不使用嚴格模式時日期有效,應檢查應用程式。
在嚴格模式,非法日期不被接受,並且不轉換。
· 包含兩位年值的日期會令人模糊,因為世紀不知道。 MySQL使用以下規則解釋兩位年值:
o 00-69範圍的年值轉換為2000-2069。
o 70-99範圍的年值轉換為1970-1999。
1.1. 自MySQL 4.1以來的TIMESTAMP屬性
註解:在舊版本的MySQL中(4.1之前),TIMESTAMP欄位類型的屬性在許多方面於本節所描述的大大不同。如果你需要將舊的TIMESTAMP資料轉換以便在MySQL 5.1中運作,詳情請參考MySQL 4.1 參考手冊。
TIMESTAMP欄位的顯示格式與DATETIME欄位相同。換句話說,顯示寬度固定在19字符,並且格式為YYYY-MM-DD HH:MM:SS。
MySQL伺服器也可以以MAXDB模式運作。當伺服器以該模式運作時,TIMESTAMP與DATETIME相等。也就是說,如果建立表時伺服器以MAXDB模式運行,TIMESTAMP列會建立為DATETIME列。結果是,該欄位使用DATETIME顯示格式,具有相同的值範圍,並且沒有自動初始化或更新目前的日期和時間。
要想啟用MAXDB模式,在啟動伺服器時使用--sql-mode=MAXDB伺服器選項或在執行時透過設定全域sql_mode變數將SQL伺服器模式設定為MAXDB:
mysql> SET GLOBAL sql_mode=MAXDB;
登入後複製
客戶端可以依照下列方法讓伺服器為它的連線以MAXDB模式運作:
mysql> SET SESSION sql_mode=MAXDB;
登入後複製
MySQL不接受在日或月列包含一個零或包含非法日期值的時間戳值。此規則的唯一例外是特殊值'0000-00-00 00:00:00'。
你可以非常靈敏地確定什麼時候初始化和更新TIMESTAMP和對哪些列進行初始化和更新:
· 你可以將當前的時間戳指定為預設值和自動更新的值。但只能選一個,或兩者都不選。 (不可能一個列選擇一個行為而另一個列選擇另一個行為)。
· 你可以指定哪個TIMESTAMP欄位會自動初始化或更新為目前的日期和時間。不再需要為第1個TIMESTAMP欄位。
請注意下面討論所資訊只適用於建立時未啟用MAXDB模式的表的TIMESTAMP欄位。 (如上所述,MAXDB模式使列建立為DATETIME列)。控制TIMESTAMP欄位的初始化和更新的規則如下所示:
· 如果一個表格內的第1個TIMESTAMP欄位指定為一個DEFAULT值,則不能忽略。 預設值可以為CURRENT_TIMESTAMP或常數日期和時間值。
· DEFAULT NULL與第1個TIMESTAMP 列的DEFAULT CURRENT_TIMESTAMP相同。對於其它TIMESTAMP列,DEFAULT NULL被視為DEFAULT 0。
· 表內的任何一個TIMESTAMP欄位可以設定為自動初始化為目前時間戳記和/或更新。
· 在CREATE TABLE語句中,可以用下面的任何一種方式聲明第1個TIMESTAMP欄位:
o 用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_MEST 的時間點。
o 不使用DEFAULT或ON UPDATE子句,且與DEFAULT CURRENT_TIMESTAMP ON UPDATECURRENT_TIMESTAMP相同。
o 用DEFAULT CURRENT_TIMESTAMP子句不用ON UPDATE子句,列為預設值使用目前的時間戳但是不自動更新。
o 不用DEFAULT子句但用ON UPDATE CURRENT_TIMESTAMP子句,列有預設值0並自動更新。
o 用常量DEFAULT值,列有给出的 默认值。如果列有一个ON UPDATE CURRENT_TIMESTAMP子句,它自动更新,否则不。
换句话说,你可以为初始值和自动更新的值使用当前的时间戳,或者其中一个使用,或者两个皆不使用。(例如,你可以指定ON UPDATE来启用自动更新而不让列自动初始化)。
· 在DEFAULT和ON UPDATE子句中可以使用CURRENT_TIMESTAMP、CURRENT_TIMESTAMP()或者NOW()。它们均具有相同的效果。
两个属性的顺序并不重要。如果一个TIMESTAMP列同时指定了DEFAULT和ON UPDATE,任何一个可以在另一个的前面。
例子,下面这些语句是等效的:
CREATE TABLE t (ts TIMESTAMP);
CREATE TABLE t (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t (ts TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
DEFAULT CURRENT_TIMESTAMP);
登入後複製
· 要为TIMESTAMP列而不是第1列指定自动默认或更新,必须通过将第1个TIMESTAMP列显式分配一个常量DEFAULT值来禁用自动初始化和更新。(例如,DEFAULT 0或DEFAULT'2003-01-01 00:00:00')。然后,对于其它TIMESTAMP列,规则与第1个TIMESTAMP列相同,例外情况是不能忽略DEFAULT和ON UPDATE子句。如果这样做,则不会自动进行初始化或更新。
例如:下面这些语句是等效的:
CREATE TABLE t (
ts1 TIMESTAMP DEFAULT 0,
ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE t (
ts1 TIMESTAMP DEFAULT 0,
ts2 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
DEFAULT CURRENT_TIMESTAMP);
登入後複製
可以对每个连接设置当前的时区。TIMESTAMP值以UTC格式保存,存储时对当前的时区进行转换,检索时再转换回当前的时区。只要时区设定值为常量,便可以得到保存时的值。如果保存一个TIMESTAMP值,应更改时区然后检索该值,它与你保存的值不同。这是因为在两个方向的转换中没有使用相同的时区。当前的时区可以用作time_zone系统变量的值。
可以在TIMESTAMP列的定义中包括NULL属性以允许列包含NULL值。例如:
CREATE TABLE t
(
ts1 TIMESTAMP NULL DEFAULT NULL,
ts2 TIMESTAMP NULL DEFAULT 0,
ts3 TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP
);
登入後複製
如果未指定NULL属性,将列设置为NULL设置则会将它设置为当前的时间戳。请注意允许NULL值的TIMESTAMP列不会采用当前的时间戳,除非要么其 默认值定义为CURRENT_TIMESTAMP,或者NOW()或CURRENT_TIMESTAMP被插入到该列内。换句话说,只有使用如下定义创建,定义为 NULL的TIMESTAMP列才会自动更新:
CREATE TABLE t (ts NULLDEFAULT CURRENT_TIMESTAMP);
登入後複製
否则-也就是说,如果使用NULL而不是DEFAULT TIMESTAMP来定义TIMESTAMP列,如下所示...
CREATE TABLE t1 (ts NULL DEFAULT NULL);
CREATE TABLE t2 (ts NULL DEFAULT '0000-00-00 00:00:00');
登入後複製
...则必须显式插入一个对应当前日期和时间的值。例如:
INSERT INTO t1 VALUES (NOW());
INSERT INTO t2 VALUES (CURRENT_TIMESTAMP);
登入後複製
2. TIME类型
MySQL以'HH:MM:SS'格式检索和显示TIME值(或对于大的小时值采用'HHH:MM:SS'格式)。TIME值的范围可以从'-838:59:59'到'838:59:59'。小时部分会因此大的原因是TIME类型不仅可以用于表示一天的时间(必须小于24小时),还可能为某个事件过去的时间或两个事件之间的时间间隔(可以大于24小时,或者甚至为负)。
你可以用各种格式指定TIME值:
· 'D HH:MM:SS.fraction'格式的字符串。还可以使用下面任何一种“非严格”语法:'HH:MM:SS.fraction'、'HH:MM:SS'、'HH:MM'、'D HH:MM:SS'、'D HH:MM'、'D HH'或'SS'。这里D表示日,可以取0到34之间的值。请注意MySQL还不保存分数。
· 'HHMMSS'格式的没有间割符的字符串,假定是有意义的时间。例如,'101112'被理解为'10:11:12',但'109712'是不合法的(它有一个没有意义的分钟部分),将变为'00:00:00'。
· HHMMSS格式的数值,假定是有意义的时间。例如,101112被理解为'10:11:12'。下面格式也可以理解:SS、MMSS、HHMMSS、HHMMSS.fraction。请注意MySQL还不保存分数。
· 函数返回的结果,其值适合TIME上下文,例如CURRENT_TIME。
对于指定为包括时间部分间割符的字符串的TIME值,如果时、分或者秒值小于10,则不需要指定两位数。'8:3:2'与'08:03:02'相同。
为TIME列分配简写值时应注意。没有冒号,MySQL解释值时假定最右边的两位表示秒。(MySQL解释TIME值为过去的时间而不是当天的时间)。例如,你可能认为'1112'和1112表示'11:12:00'(11点过12分),但MySQL将它们解释为'00:11:12'(11分,12 秒)。同样,'12'和12 被解释为 '00:00:12'。相反,TIME值中使用冒号则肯定被看作当天的时间。也就是说,'11:12'表示'11:12:00',而不是'00:11:12'。
超出TIME范围但合法的值被裁为范围最接近的端点。例如,'-850:00:00'和'850:00:00'被转换为'-838:59:59'和'838:59:59'。
无效TIME值被转换为'00:00:00'。请注意由于'00:00:00'本身是一个合法TIME值,只从表内保存的一个'00:00:00'值还不能说出原来的值是 '00:00:00'还是不合法的值。
3. YEAR類型
YEAR類型是一個單字元類型用來表示年。
MySQL以YYYY格式擷取並顯示YEAR值。範圍是1901到2155。
可以指定各種格式的YEAR值:
· 四位元字串,範圍為'1901'到'2155'。
· 四位數字,範圍為1901到2155。
· 兩位字串,範圍為'00'到'99'。 '00'到'69'和'70'到'99'範圍的值被轉換為2000到2069和1970到1999範圍的YEAR值。
· 兩位整數,範圍為1到99。1到69和70到99範圍的值被轉換為2001到2069和1970到1999範圍的YEAR值。請注意兩位整數範圍與兩位字串範圍稍有不同,因為你不能直接將零指定為數字並將它解釋為2000。你必須將它指定為一個字串'0'或'00'或它被解釋為0000。
· 函數傳回的結果,其值適合YEAR上下文,例如NOW()。
非法YEAR值被轉換為0000。
4. Y2K事宜和日期類型
MySQL本身對於2000年(Y2K)是安全的,但輸入給MySQL的值可能不安全。任何包含兩位年值的輸入都會令人模糊,因為世紀不知道。這些值必須解釋為四位元形式,因為MySQL內部使用四位元來保存年。
對於DATETIME、DATE、TIMESTAMP和YEAR類型,MySQL使用以下規則解釋含模糊年值的日期:
· 00-69範圍的年值轉換為2000-2069。
· 70-99範圍的年值轉換為1970-1999。
請記住這些規則只是合理猜測資料值表示什麼。如果MySQL使用的啟發不能產生正確的值,你應該提供包含四位年值的確切輸入。
ORDER BY可以正確排序有兩位數年的TIMESTAMP或YEAR值。
部分函數如MIN()和MAX()將TIMESTAMP或YEAR轉換為一個數字。這說明使用有兩位數年值的值,這些函數不能工作正確。在這種情況下的修復方法是將TIMESTAMP或YEAR轉換為四週年格式或使用MIN(DATE_ADD(TIMESTAMP,INTERVAL 0 DAYS))。
以上是MySQL基礎教學2 —— 資料類型之日期與時間類型的內容,更多相關內容請關注PHP中文網(m.sbmmt.com)!