我应该在MySQL中使用datetime或timestamp数据类型吗?


Answers:


1829

MySQL中的时间戳通常用于跟踪记录的更改,并且通常在每次更改记录时进行更新。如果要存储特定值,则应使用datetime字段。

如果您要决定是使用UNIX时间戳还是使用本机MySQL datetime字段,请采用本机格式。您可以通过这种方式在MySQL中进行计算, ("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")并且("SELECT UNIX_TIMESTAMP(my_datetime)")如果要使用PHP对记录进行查询,则可以很容易地将值的格式更改为UNIX时间戳。


981
一个重要的区别是,它DATETIME代表一个日期(在日历中可以找到)和一个时间(可以在挂钟上看到),而TIMESTAMP代表一个明确定义的时间点。如果您的应用程序处理时区,那么这可能非常重要。多久以前是'2010-09-01 16:31:00'?这取决于您所处的时区。对我来说,这只是几秒钟前,对您来说,它可能代表将来的时间。如果我说自“ 1970-01-01 00:00:00 UTC”以来的1283351460秒,那么您确切地知道我在说什么时间点。(请参见下文Nir的出色回答)。[缺点:有效范围]。
MattBianco 2010年

121
另一个区别是:不会缓存具有“本地”日期时间的查询,但是会缓存具有时间戳的查询。
OZ_

39
“ MySQL中的时间戳通常用于跟踪记录的更改”不要认为这是一个好答案。时间戳比MattBianco和Nir所说的要强大和复杂得多。虽然,答案的第二部分非常好。blivet说的是真的,这是一个很好的建议。
santiagobasulto

10
还有1个重要说明,DATETIME和TIMESTAMP可以分别使用CURRENT_TIMESTAMP,NOW()作为默认值,但是DATE不能使用,因为它默认使用'0000-00-00',因此要解决该问题,U应该写您自己对该表的触发器,以使用DATE mysql类型在字段/列中插入当前日期(无时间)。
亚瑟·库什曼

14
@DavidHarkness:文件说, “要指定自动属性,使用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP条款” dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
PLAP

917

在MySQL 5及更高版本中,TIMESTAMP值从当前时区转换为UTC以进行存储,并从UTC转换回当前时区以进行检索。(这仅发生在TIMESTAMP数据类型上,而不发生在其他类型上,例如DATETIME。)

默认情况下,每个连接的当前时区是服务器的时间。可以在每个连接的基础上设置时区,如MySQL服务器时区支持中所述


11
这个OReilly演示文稿非常适合该主题(PDF抱歉)cdn.oreillystatic.com/en/assets/1/event/36/…–
gcb

13
它也与事件的性质有关:-视频会议(TIMESTAMP)。所有服务员都应看到对调整到其时区的绝对时间的引用。-当地工作时间(DATETIME),无论我在纽约或巴黎工作的那一天,我都应该在2014/03/31 9:00 AM执行此任务。我将在当天当地时间8:00 AM开始工作。
yucer 2013年

1
因此,如果我更改服务器的时区,那么TIMESTAMP的值将保持不变或也会改变?
Andrew

3
@Andrew因为它是UTC,所以它将保持UTC。但是,向后转换将更改为“新”服务器时区。
nembleton

@yucer-我不建议这样考虑。在全球经济中,最一致的用法是将所有日期时间转换为UTC进行存储。按照惯例,将Datetime视为UTC字段。这确实给所有输入日期时间以转换为UTC的任务带来了负担,但是从长远来看这是一个更清洁的设计。当然,可以根据用户当前的设置向他们展示信息。如果用户希望输入“巴黎09:00”,则让他们设置巴黎时间,然后输入09:00。那么任何人谁是在纽约可以很容易地找到他们需要的时候保持清醒他们的时间,电话英寸
ToolmakerSteve

524

我总是将DATETIME字段用于行元数据(创建或修改的日期)以外的任何内容。

至于提到的 MySQL文档中:

当您需要包含日期和时间信息的值时,将使用DATETIME类型。MySQL检索并以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值。支持的范围是“ 1000-01-01 00:00:00”到“ 9999-12-31 23:59:59”。

...

TIMESTAMP数据类型的UTC范围为'1970-01-01 00:00:01'至UTC'2038-01-09 03:14:07'。它具有不同的属性,具体取决于运行服务器的MySQL版本和SQL模式。

您很可能会达到一般使用的TIMESTAMP的下限-例如,存储生日。


195
如果您在银行或房地产行业,也可以轻松达到上限 ... 30年的抵押贷款现在已超过2038
Kip 2012年

16
当然,请使用64位Unix时间戳。例如,在Java中,new Date().getTime()已经为您提供了64位值。
osa

5
DATETIME +1:在我们的数据流中,从物理商店的SQL Server进行购买和开票,然后将其转移到网页上虚拟商店的MySQL Server的网页上,DATETIME对于修改Date-Time更好,因为该数据类型也存在于Transact中-SQL。但是TIMESTAMP在Transact-SQL中还有其他含义,它类似于ROWVERSION是Binary,尽管MySQL TIMESTAMP与DateTime类似。因此,我们避免将TIMESTAMP用于两个数据库的兼容性。
雅各

10
不知道。这是一个比MySQL更大的问题,并且没有简单的解决方法:en.wikipedia.org/wiki/Year_2038_problem我不相信MySQL可以声明时间戳现在是64位,并且认为一切都会好起来的。他们不控制硬件。
scronide

5
就像我一样,如果您知道生日,生日可以是DATETIME。
克里斯·克雷格

322

下面的示例显示TIMESTAMP在更改time-zone to 'america/new_york'where DATETIME不变后日期类型如何更改值。

mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name    | Value               |
+------------------+---------------------+
| system_time_zone | India Standard Time |
| time_zone        | Asia/Calcutta       |
+------------------+---------------------+

mysql> create table datedemo(
    -> mydatetime datetime,
    -> mytimestamp timestamp
    -> );

mysql> insert into datedemo values ((now()),(now()));

mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime          | mytimestamp         |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 14:11:09 |
+---------------------+---------------------+

mysql> set time_zone="america/new_york";

mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime          | mytimestamp         |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 04:41:09 |
+---------------------+---------------------+

我已经将答案转换为文章,以便更多人可以找到有用的MySQL:日期时间与时间戳数据类型


55
嗯,实际上DATETIME有效时间随时区的变化而变化,TIMESTAMP并没有变化,但是人类的代表却发生了变化。
flindeberg 2014年

3
似乎此命令在MySQL 5.6中不起作用 set time_zone="america/new_york"
Manjunath Reddy


2
同意@flindeberg。时区更改后,时间戳表示正确的时间,而不是日期时间
Nitin Bansal,2016年

193

主要区别在于DATETIME是常数,而TIMESTAMP受time_zone设置影响。

因此,只有在跨时区拥有或将来有同步集群时,才有意义。

用简单的话来说:如果我在澳大利亚有一个数据库,并转储该数据库以在美国同步/填充一个数据库,则TIMESTAMP将更新以反映新时区的事件实时,而DATETIME会仍然反映事件在au时区的时间

在应该使用TIMESTAMP的地方使用了DATETIME的一个很好的例子是在Facebook中,那里的服务器从不十分确定跨时区发生了什么时间。在一次对话中,时间说的是我在实际发送消息之前回复消息。(当然,如果发布时间而不是同步时间,则这也可能是由于消息传递软件中的时区转换错误造成的。)


83
我认为这不是好方法。我只是将所有日期存储和处理为UTC,并确保前端根据给定的时区显示它。这种方法是简单且可预测的。
科斯2012年

8
@Kos:难道不是TIMESTAMP在内部执行的所有时间都在UTC中存储和处理吗?(然后将其转换为显示您的本地时区吗?)
carbocation 2013年

10
当地的时区?您的数据库如何知道我的时区?;-)数据库和用户界面之间通常会有很多处理。我只在整个处理后进行本地化。
科斯2013年

3
@Koz:我的数据库不知道您的数据库时区:!但是它确实知道时间戳。您的数据库知道自己的时区设置,并在解释/表示时间戳时应用它。2013年12月11日北京时间上午1:01与2013年12月11日澳大利亚悉尼上午1:01的时间并不相同。Google:“时区”和“本初子午线”。
ekerner 2013年

2
MySQL将TIMESTAMP值从当前时区转换为UTC进行存储,然后从UTC返回当前时区进行检索。(这并不适用于其他类型,例如DATETIME发生。)dev.mysql.com/doc/refman/5.5/en/datetime.html
Mahdyfo

124

我基于语义做出此决定。

当需要记录(或多或少)固定时间点时,请使用时间戳记。例如,将记录插入数据库中或发生某些用户操作时。

当日期/时间可以任意设置和更改时,我使用datetime字段。例如,当用户可以保存以后的更改约会时。


timestamp-固定时间点,协调世界时datetime-相对于某个角度,相对于时间参考(例如,时区本地时间)。
yucer 2013年

110

我建议使用既不 datetime或时间戳字段。如果您想代表一个特定的一天(例如生日),请使用DATE类型,但如果要更具体一些,则可能希望记录一个实际时刻而不是一个单位时间(天,周,月,年)。而不是使用DATETIME或TIMESTAMP,而使用BIGINT,并且只需存储自纪元以来的毫秒数(如果使用Java,则为System.currentTimeMillis())。这有几个优点:

  1. 您避免供应商锁定。几乎每个数据库都以相对相似的方式支持整数。假设您要移至另一个数据库。您是否要担心MySQL的DATETIME值之间的差异以及Oracle如何定义它们?即使在不同版本的MySQL中,TIMESTAMPS的精度也有所不同。直到最近,MySQL才支持时间戳的毫秒数。
  2. 没有时区问题。关于不同数据类型的时区会发生什么,这里有一些有见地的评论。但是,这是常识吗,您的同事都会花时间学习吗?另一方面,很难将BigINT更改为java.util.Date。使用BIGINT会导致很多时区问题掉到一边。
  3. 不用担心范围或精度。您不必担心将来的日期范围会缩短什么(TIMESTAMP仅适用于2038年)。
  4. 第三方工具集成。通过使用整数,对于第三方工具(例如EclipseLink)与数据库进行交互来说是微不足道的。并非每个第三方工具都会像MySQL一样对“日期时间”有相同的理解。想尝试在Hibernate中弄清楚如果使用的是这些自定义数据类型,则应使用java.sql.TimeStamp还是java.util.Date对象?使用您的基本数据类型可以轻松地使用第三方工具。

此问题与如何在数据库中存储货币值(即$ 1.99)密切相关。您应该使用小数,还是数据库的Money类型,还是最差的Double?由于上面列出的许多相同原因,所有这三个选项都很糟糕。解决方案是使用BIGINT将货币价值存储为美分,然后在向用户显示价值时将美分转换为美元。数据库的工作是存储数据,而不是解释该数据。您在数据库(尤其是Oracle)中看到的所有这些奇特的数据类型几乎没有增加,并开始您进入供应商锁定的道路。


12
我喜欢这个解决方案。时间戳将于2038年到期是一个主要问题。并不是那么遥远!
查理·达萨斯

4
@CharlieDalsass您认为当前的软件会在那个时候发布

13
如果将数据存储为毫秒数,将很难按日期查询数据
Ali Saeed

4
如果您关心可移植性并处理多个时区中的用户或与用户所在时区不同的数据库,这确实是最好的解决方案。如果没有设计缺陷,TIMESTAMP可能是解决之道。不幸的是,破损的解决方案获得了更多的投票,因为它们发布得早(几年!)。
德国人

4
优秀的解决方案!而您“被锁定”是完全正确的。当您养成让别人“为您完成工作”的习惯时,您就开始失去使您成为程序员的零碎东西。
fmc

98

TIMESTAMP是4个字节,而DATETIME是8个字节。

http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

但是就像scronide所说的那样,它的下限确实是1970年。尽管这对于将来可能发生的任何事情都非常有用;)


185
未来在世界标准时间2038-01-19 03:14:07结束。
MattBianco 2010年

5
太傻了 我认为TIMESTAMP类型会“面向未来”,因为它相对较新。当您使用不同的时区时,您不必费心将日期时间转换为UTC并每次都返回。他们应该使TIMESTAMP更大..至少大1个字节。它将增加68 * 255 = 17340年...尽管它不是32位对齐的。
NickSoft 2012年

10
您知道为什么TIMESTAMP会在2038年结束吗?因为它是一个整数,并且整数有2147483647个限制。我认为这是原因。可能是,如果他们将其类型更改为varchar并更改了操作方式,它将“面向未来”。
Vinsa 2015年

6
@vinsa,我认为届时将不会准备就绪。还记得Y2K错误吗?2038年即将到来。
Pacerier

2
到2038年,MySQL(如果仍然存在)将仅更新TIMESTAMP字段以使用4个以上的字节并允许更大的范围
the_nuts

95
  1. TIMESTAMP是四个字节,而DATETIME是八个字节。

  2. 时间戳在数据库上也更轻巧,索引速度更快。

  3. 当您需要包含日期和时间信息的值时,将使用DATETIME类型。MySQL检索并以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值。支持的范围是'1000-01-01 00:00:00'至'9999-12-31 23:59:59'。

TIMESTAMP数据类型的UTC范围为'1970-01-01 00:00:01'UTC至'2038-01-09 03:14:07'UTC。它具有不同的属性,具体取决于运行服务器的MySQL版本和SQL模式。

  1. DATETIME是常数,而TIMESTAMP受time_zone设置影响。

6
您需要澄清#4:存储的时间戳与时区是恒定且非相对的(完全不可知),而检索时显示的输出受请求会话的时区影响。DATETIME始终是相对于其记录的时区的,因此必须始终在这种情况下加以考虑,这是现在应用程序的责任。
Christopher McGowan

1
好答案。要添加到此答案中,如果我们尝试存储超出'2038-01-09 03:14:07'的值,我们将得到一个错误或将其存储为'0000-00-00 00:00:00'。我的数据库出现此错误,因为它具有时移值(出于加密目的)。
KarthikS

此外,在低于5.5的mysql版本上,DATETIME的DEFAULT值存在问题。dba.stackexchange.com/questions/132951/…–
Velaro

47

确实取决于应用程序。

考虑为用户在纽约的服务器上设置时间戳,以在上海约会。现在,当用户在上海聊天时,他可以从东京的镜像服务器访问相同的约会时间戳。他将在东京时间看到约会,而不是原来的纽约时间。

因此,对于表示用户时间的值(如约会或时间表),日期时间更好。无论服务器设置如何,它都允许用户控制所需的确切日期和时间。设置时间是设置时间,不受服务器的时区,用户的时区或夏时制的计算方式(是的,并且会更改)的影响。

另一方面,对于表示系统时间的值(例如付款交易,表修改或日志记录),请始终使用时间戳记。将服务器移至另一个时区,或在不同时区的服务器之间进行比较时,系统均不会受到影响。

时间戳在数据库上也更轻巧,索引速度更快。


您的应用程序不应依赖于服务器的时区。应用程序应始终在发出任何查询之前在其使用的数据库连接会话中选择时区。如果多个用户(例如:webapp)之间共享连接,请使用UTC并在呈现端进行时区转换。
支石墓

42

2016 +:我建议将Mysql时区设置为UTC并使用DATETIME:

任何最新的前端框架(Angular 1/2,react,Vue等)都可以轻松,自动地将您的UTC日期时间转换为本地时间。

另外:

  • 现在可以将DATETIME 自动设置为当前时间值。如何为MySQL Datetime列设置默认值?
  • 与人们可能想到的相反,DATETIME比时间戳更快速http//gpshumano.blogs.dri.pt/2009/07/06/mysql-datetime-vs-timestamp-vs-int-performance-and-benchmarking-with -myisam /
  • 时间戳仍限于1970-2038

(除非您可能会更改服务器的时区)


AngularJs的示例

// back-end: format for angular within the sql query
SELECT DATE_FORMAT(my_datetime, "%Y-%m-%dT%TZ")...

// font-end Output the localised time
{{item.my_datetime | date :'medium' }}

此处提供所有本地化的时间格式:https//docs.angularjs.org/api/ng/filter/date


8
您的数据不应附加到服务器的时区设置中。也许,如果您的桌子底下有一个MySql框,这对您很有效
Jin

@Jin UTC表示没有像TIMESTAMP这样的时区。如果所有服务器都位于UTC中,则没有问题。如果您具有2000的配置,则可能对您不起作用。
塞巴斯蒂安·霍林

将来,TIMESTAMP可能会升级为64位值。这样就没有其他问题了。
twojr

加载整个第三方库以捕获类似内容对性能也不会那么好,不是吗?鉴于它是客户端,并且不会影响您的数据库...尽管如此,您在前端做的任何事情都需要服务器端检查。所以,思维的完整画面,它真的与速度问题上需要帮助?-我觉得这些基准有些奇怪。在查询中使用字符串比较时间戳字段也感觉很奇怪。那也必须损害性能,对吗?
NoobishPro

1
不要将您的应用程序依赖于服务器的time_zone。而是定义要在每个数据库连接上使用的time_zone:SET time_zone = '+0:00';用于UTC。
支石墓

37

一个timestamp字段是一个特例datetime场。您可以创建timestamp具有特殊属性的列。可以将其设置为在创建和/或更新时自行更新。

用“更大”的数据库术语来说,上面timestamp有几个特殊情况的触发器。

正确的选择完全取决于您想做什么。


6
不,区别不只是“特殊情况”。因为设置/查询会话的时区涉及的值不同。
支石墓

我很高兴您提出“正确的选择完全取决于您想做什么”。在SE上有太多的答案指出,没有充分的理由,“您绝不能做X”或“您必须总是做Y”。
Agi Hammerthief

37

TIMESTAMP始终使用UTC(即,从1970-01-01开始,经过的秒数,使用UTC),并且您的MySQL服务器会自动将其转换为连接时区的日期/时间。从长远来看,TIMESTAMP是必经之路,因为您知道您的时间数据将始终采用UTC。例如,如果您迁移到其他服务器或更改服务器上的时区设置,则不会浪费日期。

注意:默认连接时区是服务器时区,但是可以(应该)针对每个会话进行更改(请参阅参考资料SET time_zone = ...)。



24

值得注意的是,在MySQL中,创建表列时可以使用以下内容:

on update CURRENT_TIMESTAMP

这将在您修改行的每个实例上更新时间,有时对于存储上一次编辑信息很有帮助。这仅适用于时间戳,但不适用于日期时间。


23

在使用MySQL和PHP时,我总是会使用Unix时间戳。这样做的主要原因是PHP中默认的date方法使用时间戳作为参数,因此不需要解析。

要在PHP中获得当前的Unix时间戳,只需time();
在MySQL中执行即可SELECT UNIX_TIMESTAMP();


6
-1我实际上认为下面的答案更好-使用datetime可以将更多用于日期处理的逻辑推入MySQL本身,这可能非常有用。
Toby Hede,

是否有基准测试表明MySQL的排序速度比php慢?
sdkfasldf,2010年

取决于它,有时候当我们不想使用strtotime时最好使用它。(php5.3 dep)
Adam Ramadhan's

您可以根据需要通过仅使用FROM_UNIXTIME将逻辑推入mysql中
inarilo

我曾经在我的PHP应用程序和MySQL中使用所有Unix时间戳,但是我发现将日期和时间作为本机日期/时间类型存储在MySQL中要方便得多。这对于报表目的和仅浏览数据集特别有用。随着时间的流逝,由于不得不复制/粘贴Unix时间戳而感到沮丧,我开始进行切换。我可以肯定它具有性能和其他优点/缺点,但是取决于您的用例,便捷性可能比相当的微优化更重要。
DavidScherer

17

根据我的经验,如果您希望只在其中插入一次的日期字段,并且不想对该特定字段进行任何更新或任何其他操作,请选择date time

例如,考虑一个user带有REGISTRATION DATE字段的表。在该user表中,如果您想知道特定用户的上次登录时间,请使用时间戳类型的字段,以便该字段得到更新。

如果从phpMyAdmin创建表,则默认设置将在发生行更新时更新timestamp字段。如果您的时间戳字段未通过行更新进行更新,则可以使用以下查询使时间戳字段自动更新。

ALTER TABLE your_table
      MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

15

时间戳记数据类型存储日期和时间,但以UTC格式存储,而不是像datetime那样以当前时区格式存储。当您获取数据时,时间戳再次将其转换为当前时区时间。

因此,假设您在美国,并且从具有美国时区的服务器获取数据。然后您将根据美国时区获得日期和时间。当时间戳记数据类型列的行被更新时,它总是自动更新。因此,跟踪上次更新特定行的时间可能很有用。

有关更多详细信息,您可以阅读博客文章Timestamp Vs Datetime


您可以(应该)始终使用SET time_zone = '+0:00';(此处为UTC)在会话级别定义时区,以确保您从TIMESTAMP值中获取/设置了什么,并避免依赖于可能更改的服务器time_zone默认值。
支石墓

14

我始终使用Unix时间戳,只是为了在处理大量日期时间信息时保持理智,尤其是在对时区进行调整,添加/减去日期等时。比较时间戳时,它排除了时区的复杂因素,并允许您在服务器端处理(无论是应用程序代码还是数据库查询)中节省资源,因为您使用的是轻量级算法,而不是较重的日期时间加/减功能。

另一件事值得考虑:

如果要构建应用程序,则永远都不知道可能必须如何使用数据。如果您不得不将数据集中的一堆记录与第三方API的一堆项目进行比较,并按时间顺序排列它们,您将很高兴拥有行的Unix时间戳。即使您决定使用MySQL时间戳,也要存储Unix时间戳作为保险。


14

就我而言,我会尽可能将UTC设置为所有区域的时区:系统,数据库服务器等。如果我的客户需要另一个时区,那么我可以在应用程序上对其进行配置。

我几乎总是喜欢时间戳而不是日期时间字段,因为时间戳隐式包含时区。因此,由于从不同时区的用户访问应用程序的那一刻起,您就希望他们看到其本地时区中的日期和时间,因此与将数据保存在datetime字段中相比,此字段类型使操作起来非常容易。

另外,在将数据库迁移到具有其他时区的系统的情况下,使用时间戳会使我更有信心。更不用说当计算两个时刻之间的差并且两者之间的加法器时间改变并且需要1小时或更短的精度时可能出现的问题。

因此,总而言之,我重视时间戳的优点:

  • 准备在国际(多时区)应用程序上使用
  • 在时区之间轻松迁移
  • 非常容易计算差异(只需减去两个时间戳)
  • 不用担心夏季时段的日期

由于所有这些原因,我在可能的地方选择UTC和时间戳字段。而且我避免头痛;)


2038年1月20日到来时,时间戳数据对于支持您的应用程序的人员将非常有趣。滴答滴答滴答滴答滴答
威尔逊·哈克

然后可以将时间戳类型增加一点,并使可能的值加倍。
罗杰·坎帕内拉

测试您的理论以“稍微增加”,看看是否可以成功存储2038年2月1日并使用MySQL检索它。请看一下完成后的表定义。您可能会在2038
Wilson Hauck

1
@WilsonHauck无论如何,您都必须在2038年之前很长时间升级MySQL版本。扩展的TIMESTAMP将由迁移处理。此外,除了处理抵押贷款外,几乎没有其他应用程序现在真正需要关心2038年。
支石墓

@dolmen许多专业级工具和材料都有20年以上的保修。因此,类似warranties.expires_at今天的MySQL时间戳已不可能。
alexw

13

在表上执行UPDATE语句时,请注意时间戳的更改。如果您的表具有“名称”(varchar),“年龄”(int)和“ Date_Added”(时间戳)列,则运行以下DML语句

UPDATE table
SET age = 30

那么“ Date_Added”列中的每个单个值都将更改为当前时间戳。


3
根据您如何设置表格,您可以控制此行为。看dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
查尔斯Faiga

5
@CharlesFaiga默认行为是在更新任何其他列时更新时间戳。如果希望时间戳保留其原始值,则必须明确将其关闭
Lloyd Banks

那是什么 ?!您必须将timstamp列设置为ON UPDATE CURRENT_TIMESTAMP
Accountantم

创建表时必须明确启用此功能
支石墓

13

从本文引用:

主要区别:

TIMESTAMP用于跟踪记录的更改,并在每次记录更改时进行更新。DATETIME用于存储不受记录更改影响的特定和静态值。

TIMESTAMP还受与TIME ZONE相关的其他设置的影响。DATETIME是常数。

TIMESTAMP在内部将当前时区转换为UTC进行存储,并在检索过程中将其转换回当前时区。DATETIME无法做到这一点。

支持的TIMESTAMP范围:'1970-01-01 00:00:01'UTC到'2038-01-19 03:14:07'UTC DATETIME支持的范围:'1000-01-01 00:00:00'到'9999 -12-31 23:59:59′


11
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
|                                       TIMESTAMP                                       |                                 DATETIME                                 |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP requires 4 bytes.                                                           | DATETIME requires 8 bytes.                                               |
| Timestamp is the number of seconds that have elapsed since January 1, 1970 00:00 UTC. | DATETIME is a text displays 'YYYY-MM-DD HH:MM:SS' format.                |
| TIMESTAMP supported range: 1970-01-01 00:00:01 UTC to 2038-01-19 03:14:07 UTC.    | DATETIME supported range: 1000-01-01 00:00:00 to 9999-12-31 23:59:59 |
| TIMESTAMP during retrieval converted back to the current time zone.                   | DATETIME can not do this.                                                |
| TIMESTAMP is used mostly for metadata i.e. row created/modified and audit purpose.    | DATETIME is used mostly for user-data.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+

10

时间戳和日期时间之间的另一个区别是在时间戳中,您不能将默认值设置为NULL。


8
这显然是错误的。这是一个示例: CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);第一列可以接受NULL值。
Ormoz

10

我发现TIMESTAMP能够根据当前时间自动更新自身而无需使用不必要的触发器,这具有无与伦比的实用性。尽管那是我所说的,尽管TIMESTAMP就像上面所说的那样是UTC。

它可以跟踪不同时区,因此,例如,如果需要显示相对时间,则需要UTC时间。



9

datetime在遇到许多与时区有关的问题和错误后,我停止在自己的应用程序中使用。恕我直言,使用timestampdatetime大多数情况下更好

当您问几点了?答案来了像'2019-02-05 21:18:30'之类的东西,它没有完成,没有定义答案,因为它缺少另一个部分,在哪个时区?华盛顿?莫斯科?北京?

使用不带时区的datetimes意味着您的应用程序仅处理1个时区,但是时间戳为您提供了好处,datetime并且可以灵活地显示不同时区中的相同精确时间点。

在某些情况下,您会后悔使用datetime并希望将数据存储在时间戳中。

  1. 为了让您的客户感到舒适,您想根据他们的首选时区向他们显示时间,而无需让他们进行数学运算并将时间转换为有意义的时区。您所需要做的就是更改时区,所有应用程序代码都将相同。(实际上,您应该始终在应用程序启动时定义时区,或者在PHP应用程序的情况下请求处理)

    SET time_zone = '+2:00';
  2. 您更改了所居住的国家/地区,并继续维护数据,同时在其他时区查看数据(不更改实际数据)。

  3. 您接受来自世界各地不同客户的数据,每个客户都会在其时区中插入时间。

简而言之

datetime =应用程序支持1个时区(用于插入和选择)

timestamp =应用程序支持任何时区(用于插入和选择)


该答案仅是为了强调时区的灵活性和时间戳的易用性,而没有涵盖列大小,范围或分数之类的任何其他差异。


如果在一个表中有使用的字段date,而其他字段使用timestamp该字段怎么办。我认为这将引起一个新问题,因为被筛选的数据where与时区更改不一致。
Erlang P

@ErlangP在这种情况下,您的应用程序应date在发送查询之前解决列上的时区问题。
会计师م

7

我更喜欢使用时间戳,以便将所有内容保持为一种通用的原始格式,并以PHP代码或SQL查询格式设置数据格式。在某些情况下,您的代码中会用到它来使所有内容保持在几秒钟之内。



6

我喜欢Unix时间戳,因为您可以转换为数字,而不必担心数字。另外,您可以添加/减去并获取持续时间等。然后将结果以任何格式转换为Date。此代码找出从文档时间戳到当前时间之间经过了多少分钟的时间。

$date  = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now  - $result) / 60);
$min = round($unix_diff_min);

4
或者,使用人类可读的本机MySQL日期时间,并使用本机MySQL函数添加/减去日期时间。
朱利安·帕拉德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.