我应该在MySQL中使用日期时间或时间戳数据类型吗?

kar*_*ins 2598 mysql datetime timestamp sqldatatypes

您会建议使用日期时间时间戳字段,以及为什么(使用MySQL)?

我在服务器端使用PHP.

小智 1772

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

如果您想要在使用UNIX时间戳或本机MySQL日期时间字段之间做出决定,请使用本机格式.您可以通过这种方式在MySQL中进行计算, 如果要使用PHP对其进行操作,则可以在查询记录时("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")将值的格式更改为UNIX时间戳("SELECT UNIX_TIMESTAMP(my_datetime)").

  • 一个重要的区别是"DATETIME"表示日期(在日历中找到)和时间(可以在挂钟上观察到),而"TIMESTAMP"表示明确定义的时间点.如果您的应用程序处理时区,这可能非常重要.多久以前'2010-09-01 16:31:00'?这取决于你所在的时区.对我而言,就在几秒钟前,对你而言,它可能代表着未来的一段时间.如果我说'1970-01-01 00:00:00 UTC'之后的1283351460秒,你就知道我到底在什么时间点谈论.(见下面Nir的优秀答案).[下行:有效范围]. (942认同)
  • 另一个区别是:具有"本机"日期时间的查询将不会被缓存,但具有时间戳的查询将是. (117认同)
  • "MySQL中的时间戳通常用于跟踪记录的变化"不要认为这是一个很好的答案.时间戳比MattBianco和Nir所说的更加强大和复杂.虽然,答案的第二部分非常好.blivet说的是真的,这是一个很好的建议. (33认同)
  • @DavidHarkness:文档说"要指定自动属性,请使用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句"http://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html (14认同)
  • 另外一个重要的注意事项,DATETIME和TIMESTAMP可以使用CURRENT_TIMESTAMP,NOW()作为它的默认值,但DATE例如不能,因为它默认使用'0000-00-00',所以要解决这个问题你应该写您自己触发该表,在DATE mysql类型的字段/ col中插入当前日期(没有时间). (10认同)
  • "并且每次更改记录时都会更新"这是真的吗?每当更改行时,时间戳字段会自动更新为当前时间? (8认同)
  • 作为对@zeusakm的响应,存在一个限制,即每个表只有一个时间戳列可以具有默认的current_timestamp设置. (4认同)
  • @chaiguy - 我在文档中找不到对此的引用,并且使用MySQL 5.5进行测试表明,当我更新行时,`TIMESTAMP`列未被*更改. (4认同)
  • 这个答案在各个方面都是完全错误的。 (4认同)
  • @OZ_:当然,具有静态DATETIME值的查询将由mysql缓存.涉及`NOW()`,`CURDATE()`和类似函数的查询将不会被缓存.您可以缓存所有只包含每次都为同一参数返回相同值的函数的查询. (3认同)
  • @NobleUplift https://dev.mysql.com/doc/refman/5.5/en/query-cache-operation.html - 从大约一半的文本开始,有查询缓存不支持的函数列表以及一些其他限制和解释如何比较查询... (3认同)
  • @zeusakm,如此处所述http://stackoverflow.com/questions/23153822/mysql-datetime-default-current-timestamp-error#answer-23153922,添加了`DEFAULT CURRENT_TIMESTAMP`对'DATETIME`(数据类型)的支持在MySQL 5.6中. (3认同)
  • @Fattie 你能说得更具体一点吗?或者也许提供您自己的答案? (3认同)
  • "如果您想要在使用UNIX时间戳或本机MySQL日期时间字段之间做出决定,请使用本机格式." - 为什么?有关其他意见,请参见http://billauer.co.il/blog/2009/03/mysql-datetime-epoch-unix-time/. (2认同)

Nir*_*Nir 891

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

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

  • 它还涉及活动的性质: - 视频会议(TIMESTAMP).所有参加者都应该看到根据时区调整的绝对时间. - 本地任务时间(DATETIME),我应该在2014/03/31 9:00 AM完成这项任务,如果那天我在纽约或巴黎工作,那就无所谓了.我将在当地时间上午8点开始工作,我将在那一天. (11认同)
  • 这个OReilly演讲非常适合这个主题(PDF抱歉)http://cdn.oreillystatic.com/en/assets/1/event/36/Time%20Zones%20and%20MySQL%20Presentation.pdf (9认同)
  • @Andrew因为它是UTC,所以它将保持UTC。但是,向后转换将更改为“新”服务器时区。 (3认同)

scr*_*ide 497

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

至于提到的 MySQL文档中:

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

...

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

您很可能在一般使用中达到TIMESTAMPs的下限 - 例如存储生日.

  • 如果你在银行业或房地产业,你也可以轻松达到*上限*... 30年期抵押贷款现在超过2038年 (180认同)
  • 当然,使用64位Unix时间戳.例如,在Java中,`new Date().getTime()`已经为您提供了64位值. (16认同)
  • 不知道.这是一个比MySQL更大的问题而且没有简单的修复:http://en.wikipedia.org/wiki/Year_2038_problem我不相信MySQL只能声明时间戳现在是64位并假设一切都会好的.他们不控制硬件. (10认同)
  • 为DATETIME +1:在我们的数据流中,从物理商店的SQL Server购买和发票,转移到网页上的虚拟商店的MySQL服务器,DATETIME更适合修改日期时间,因为此数据类型也存在于Transact中 - SQL.但是TIMESTAMP在Transact-SQL中意味着其他东西,它就像ROWVERSION一样是Binary,尽管MySQL TIMESTAMP与DateTime类似.因此,我们避免使用TIMESTAMP来兼容两个DB. (5认同)
  • 如果你知道出生的时间,生日可以是一个DATETIME,就像我对我的一样. (5认同)
  • @scronide,2038年即将来临.他们(mysql)计划扩大范围吗? (3认同)

mr_*_*air 314

以下示例显示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 |
+---------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

我已将我的答案转换为文章,因此更多人可以发现这个有用的MySQL:日期时间与时间戳数据类型.

  • 好吧,实际上`DATETIME`有效时间随时区变化而变化,'TIMESTAMP`没有改变,但人类代表确实如此. (52认同)
  • 好像这个命令在MySQL 5.6中没有用.`set time_zone ="america/new_york"`; (3认同)
  • 同意@flindeberg.时区更改后,时间戳表示正确的时间,而不是日期时间 (2认同)

eke*_*ner 187

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

因此,只有当您拥有 - 或者将来可能 - 跨时区同步集群时才会这样做.

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

应该使用TIMESTAMP的DATETIME的一个很好的例子是在Facebook,他们的服务器永远不能确定跨时区发生的时间.一旦我进行了一次对话,其中的时间表示我在实际发送消息之前回复了消息.(当然,如果发布时间而不是同步时间,也可能是由于消息传递软件中的时区转换不好引起的.)

  • 我不认为这是一种好的思维方式.我只是以UTC格式存储和处理所有日期,并确保前端根据给定的时区显示它.这种方法简单且可预测. (81认同)
  • _my_当地时区?您的数据库如何知道我的时区?;-)数据库和用户界面之间通常有一些处理.我只在整个处理后进行本地化. (9认同)
  • @Kos:是不是正确存储和处理UTC中所有日期正是TIMESTAMP在内部做的事情?(然后将其转换为显示您当地的时区?) (8认同)
  • @Koz:我的数据库不知道你的数据库时区:!但它确实知道时间戳.您的数据库知道自己的时区设置,并在解释/表示时间戳时应用它.2013年12月11日上午1:01在北京中国与2013年12月11日凌晨1点01分在澳大利亚悉尼举行的时间不同.谷歌:'时区'和'本初子午线'. (3认同)
  • MySQL将TIMESTAMP值从当前时区转换为UTC进行存储,然后从UTC返回当前时区进行检索。(对于其他类型,例如DATETIME,则不会发生这种情况。)https://dev.mysql.com/doc/refman/5.5/en/datetime.html (2认同)

小智 121

我在语义基础上做出这个决定.

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

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


use*_*141 98

我建议既不使用DATETIME也不使用TIMESTAMP字段.如果你想要表示一个特定的日子(如生日),那么使用DATE类型,但如果你比那更具体,你可能有兴趣记录一个实际的时刻,而不是一个单位的时间(日,周,月,年).使用BIGINT而不是使用DATETIME或TIMESTAMP,只需存储自纪元以来的毫秒数(如果您使用的是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美元)密切相关.你应该使用Decimal,还是数据库的Money类型,或者最糟糕的Double?由于上面列出的许多相同原因,所有这三个选项都很糟糕.解决方案是使用BIGINT将货币价值存储在美分中,然后在向用户显示价值时将美分转换为美元.数据库的工作是存储数据,而不是用于表示数据.您在数据库(尤其是Oracle)中看到的所有这些奇特的数据类型几乎没有增加,并且开始向供应商锁定.

  • 如果数据存储为毫秒数,则很难按日期查询数据 (12认同)
  • 我喜欢这个解决方案.TIMESTAMP在2038年到期是一个主要问题.那真的不是那么遥远! (11认同)
  • @CharlieDalsass你认为当时的软件会在那里:-P (4认同)
  • 如果您关心多个时区的可移植性和处理用户,或者与用户在不同时区的数据库,这确实是最佳解决方案.如果没有设计缺陷,TIMESTAMP可能会成为可能.太糟糕了,破碎的解决方案获得了更多的选票,因为它们是早期发布的(多年!). (4认同)
  • 优秀解决方案 你完全正确地被"锁定"了.当你养成让别人"为你工作"的习惯时,你开始失去让你成为程序员的点点滴滴. (4认同)
  • @Merc 不,不应该。数据结构中的语义_是_一个事物_是有原因的_。数据库引擎也有语义类型_有原因_。如果您根本不关心语义,那么为什么首先使用 RDBMS(关系型 -> 基于数据之间的语义关系)? (3认同)
  • 我遇到了[遇到TIMESTAMP的麻烦](http://stackoverflow.com/questions/31582537/mysql-timestamp-to-qdatetime-with-milliseconds).这种BIGINT替代方案似乎更好. (2认同)
  • 我也选择了Bigint.存储很便宜.前端创建您想要的任何日期符号.查询范围没有问题(需要某一天,查询范围).与任何系统都非常兼容. (2认同)
  • 这应该是公认的答案。我鄙视任何一种“原生”日期格式。无尽的时区捕获等。 (2认同)

Ale*_*lex 95

对于DATETIME,TIMESTAMP是4字节Vs 8字节.

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

但是像scronide说它确实有一个1970年的下限.它对于未来可能发生的任何事情都很好;)

  • 未来将于2038-01-19 03:14:07 UTC结束. (183认同)
  • 你知道为什么TIMESTAMP会在2038年结束吗?因为它是一个整数,整数有限制,即2147483647.我认为这就是原因.可能是如果他们将其类型更改为varchar并改变了如何操作它的方式,它将是"未来就绪". (10认同)
  • @vinsa,我认为那时候它还没有准备好.还记得Y2K的bug吗?**2038即将到来.** (6认同)
  • 那太愚蠢了.我认为TIMESTAMP类型将"未来就绪",因为它相对较新.每次使用不同的时区时,都无法将日期时间转换为UTC并返回.他们应该让TIMESTAMP更大..至少增加1个字节.它将增加68*255 = 17340多年...虽然它不会是32位对齐. (5认同)
  • 到2038年,MySQL(如果仍然存在)将仅更新TIMESTAMP字段以使用4个以上的字节,并允许更大的范围 (2认同)
  • 对于在 64 位平台上运行的 MySQL 8.0.28 及更高版本,UNIX_TIMESTAMP() 的参数值的有效范围是 '1970-01-01 00:00:01.000000' UTC 到 '3001-01-19 03:14:07.999999 ' UTC(对应于 32536771199.999999 秒)。 (2认同)

Viv*_*k S 94

  1. 对于DATETIME,TIMESTAMP是4个字节对8个字节.

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

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

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

  1. 当TIMESTAMP受time_zone设置影响时,DATETIME是常量.

  • 您需要澄清#4:存储的时间戳是恒定的,非相对(完全不可知)到时区,而检索时显示的输出受请求会话的时区影响.DATETIME始终相对于记录的时区,并且必须始终在该上下文中考虑,现在责任归于应用程序. (6认同)

ian*_*aré 46

真的,取决于应用程序.

考虑将用户的时间戳设置为纽约的服务器,以便在Sanghai进行预约.现在,当用户在Sanghai连接时,他从东京的镜像服务器访问相同的约会时间戳.他将在东京时间看到这一任命,与原纽约时间相抵.

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

另一方面,对于表示系统时间的值,如支付事务,表修改或日志记录,请始终使用时间戳.将服务器移动到另一个时区,或者在不同时区的服务器之间进行比较时,系统不会受到影响.

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


Seb*_*rin 41

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

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

另外:

  • DATETIME现在可以自动设置为当前时间值如何设置MySQL Datetime列的默认值?
  • 与人们的想法相反,DATETIME比TIMESTAMP 更快, http://gpshumano.blogs.dri.pt/2009/07/06/mysql-datetime-vs-timestamp-vs-int-performance-and-benchmarking-with -myisam /
  • TIMESTAMP仍然限于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' }}
Run Code Online (Sandbox Code Playgroud)

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

  • 您的数据不应附加到服务器的时区设置.也许,如果您的桌面下有单个MySql盒子,那么它可以为您服务 (7认同)

小智 36

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

在"更大"的数据库术语中,timestamp有几个特殊情况触发器.

正确的取决于你想做什么.

  • 不,差异不仅仅是"一个特例".因为设置/查询值的会话的时区涉及不同. (6认同)

小智 34

TIMESTAMP始终为UTC(即1970-01-01以来经过的秒数,以UTC为单位),并且您的MySQL服务器会自动将其转换为服务器时区的日期/时间.从长远来看,TIMESTAMP是最佳选择,因为您知道您的时态数据将始终为UTC.例如,如果您迁移到其他服务器或更改了服务器上的时区设置,则不会将日期搞定.


Wil*_*ken 31

两者都不。对于通用用例,DATETIMETIMESTAMP类型从根本上被破坏了。MySQL 将在未来改变它们。您应该使用BIGINT和 UNIX 时间戳,除非您有特定的理由使用其他东西。

特别案例

在某些特定情况下,您的选择更容易,并且您不需要此答案中的分析和一般建议。

  • 仅日期- 如果您只关心日期(例如下一个农历新年的日期,2022-02-01)并且您清楚地了解该日期适用的时区(或不关心,如情况农历新年)然后使用DATE列类型。

  • 记录插入时间——如果您正在记录数据库中行的插入日期/时间,并且您不关心您的应用程序会在接下来的 17 年内中断,那么继续并使用TIMESTAMP默认值CURRENT_TIMESTAMP()

为什么TIMESTAMP坏了?

TIMESTAMP类型以 UTC 时区存储在磁盘上。这意味着如果您物理移动服务器,它不会损坏。那挺好的 ?。但是当前定义的时间戳将在 2038 年完全停止工作?。

每次INSERT INTOSELECT FROMTIMESTAMP列中,您的客户端/服务器应用程序的物理位置(即配置时区)的考虑。如果您移动应用程序服务器,那么您的日期会中断吗?。

为什么VARCHAR坏了?

VARCHAR类型允许以 ISO 8601 格式明确存储非本地日期/时间/两者,它适用于 2037 年以后的日期。使用祖鲁时间很常见,但 ISO 8601 允许对任何偏移进行编码。这不太有用,因为虽然 MySQL 日期和时间函数确实支持字符串作为任何日期/时间/两者都需要的输入,但如果输入使用时区偏移量,则结果不正确。

VARCHAR使用额外的存储字节。

为什么DATETIME坏了?

ADATETIME将 aDATE和 a存储TIME在同一列中。除非理解时区,否则这些东西都没有任何意义,并且时区不存储在任何地方?。您应该将预期的时区作为注释放在列中,因为时区与数据密不可分。很少有人使用专栏评论,因此这是等待发生的错误。我从亚利桑那州继承了一台服务器,所以我总是需要将所有时间戳从亚利桑那州时间转换为另一个时间。

唯一DATETIME正确的情况是完成这句话:

您的 2020 年太阳能新年恰好开始于DATETIME("2020-01-01 00:00:00")

DATETIMEs没有其他好的用途。也许您会想象特拉华州的市政府有一个 Web 服务器。该服务器的时区以及访问该服务器的所有人员都可以暗示在特拉华州,东部时区,对吧?错误的!在这个千年里,我们都认为服务器存在于“云”中。因此,在任何特定时区考虑您的服务器总是错误的,因为您的服务器总有一天会被移动。

注:现在MySQL的支持时区偏移DATETIME文字(谢谢@Marko)。这可能使插入DATETIME对您更方便,但并没有解决数据的不完整和无用意义,这个致命的问题标识了上面的(“?”)。

如何使用BIGINT

定义:

CREATE TEMPORARY TABLE good_times (
    a_time BIGINT
)
Run Code Online (Sandbox Code Playgroud)

插入特定值:

INSERT INTO good_times VALUES (
    UNIX_TIMESTAMP(CONVERT_TZ("2014-12-03 12:24:54", '+00:00', @@global.time_zone))
);
Run Code Online (Sandbox Code Playgroud)

或者当然这对您的应用程序来说要好得多,例如:

$statement = $myDB->prepare('INSERT INTO good_times VALUES (?)');
$statement->execute([$someTime->getTimestamp()]);
Run Code Online (Sandbox Code Playgroud)

选择:

SELECT a_time FROM good_times;
Run Code Online (Sandbox Code Playgroud)

有一些过滤相对时间的技术(选择过去 30 天内的帖子,查找注册后 10 分钟内购买的用户)超出了此处的范围。

  • 我还是不明白这有什么意义。如果您以 UTC 存储任何日期,并以 UTC 运行所有服务器,您就会清楚地了解您的数据。因此,您可以将日期提供给客户端“2022-01-23T09:59:56+00:00”,并且他们可以根据用户的时区应用格式。我在这里缺少什么? (3认同)

Deh*_*oos 27

DATETIME,TIMESTAMP和DATE之间的比较

在此输入图像描述

什么是[.fraction]?

  • DATETIME或TIMESTAMP值可以包括高达微秒(6位)精度的尾随小数秒部分.特别是,插入DATETIME或TIMESTAMP列的值中的任何小数部分都将被存储而不是被丢弃.这当然是可选的.

资料来源:


lee*_*phy 24

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

on update CURRENT_TIMESTAMP
Run Code Online (Sandbox Code Playgroud)

这将更新您修改行的每个实例的时间,有时对存储的最后编辑信息非常有用.这仅适用于时间戳,而不适用于日期时间.


Mar*_*son 22

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

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

  • -1我实际上认为下面的答案更好 - 使用datetime可以将更多的日期处理逻辑推送到MySQL本身,这非常有用. (6认同)

Kan*_*sad 17

根据我的经验,如果您想要一个只插入一次的日期字段,并且您不希望对该特定字段进行任何更新或任何其他操作,请使用日期时间.

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

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

ALTER TABLE your_table
      MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)


小智 15

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

因此,假设您在美国并从具有美国时区的服务器获取数据.然后,您将根据美国时区获取日期和时间.时间戳数据类型列在其行更新时始终自动更新.因此,跟踪上次更新特定行的时间非常有用.

有关详细信息,请阅读博客文章Timestamp Vs Datetime.


Oli*_*erg 14

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

另一件值得考虑的事:

如果您正在构建应用程序,那么您永远不会知道如何在线下使用您的数据.如果你不得不比较你的数据集中的一堆记录,比如来自第三方API的一堆项目,并说,按照时间顺序排列它们,你会很高兴有您的行的Unix时间戳.即使您决定使用MySQL时间戳,也要将Unix时间戳存储为保险.


Llo*_*nks 13

在表上执行UPDATE语句时要小心时间戳更改.如果您有一个包含列'Name'(varchar),'Age'(int)和'Date_Added'(timestamp)的表,并运行以下DML语句

UPDATE table
SET age = 30
Run Code Online (Sandbox Code Playgroud)

那么'Date_Added'列中的每个值都将更改为当前时间戳.

  • @CharlesFaiga默认行为是在更新任何其他列时更新时间戳.如果希望时间戳保留其原始值,则必须明确禁用此功能 (5认同)
  • 根据您设置表的方式,您可以控制此行为.看看http://dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html (3认同)

Anv*_*esh 13

参考本文:

主要区别:

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

TIMESTAMP还受到与TIME ZONE相关的不同设置的影响.DATETIME是不变的.

TIMESTAMP在内部将当前时区转换为UTC以进行存储,并在检索期间将其转换回当前时区.DATETIME无法做到这一点.

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


Rog*_*era 13

在我的例子中,我将UTC设置为所有内容的时区:系统,数据库服务器等.如果我的客户需要另一个时区,那么我在应用程序上配置它.

我几乎总是喜欢时间戳而不是日期时间字段,因为时间戳隐含地包含时区.因此,由于应用程序将从不同时区的用户访问,并且您希望他们在本地时区中查看日期和时间,因此该字段类型使得它比在日期时间字段中保存数据更容易.

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

总而言之,我重视时间戳的这些优点:

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

出于所有这些原因,我选择了有效的UTC和时间戳字段.我避免头痛;)

  • @WilsonHauck 无论如何,你必须在 2038 年之前很久就升级 MySQL 版本。扩展的 TIMESTAMP 将由迁移处理。此外,除了处理抵押贷款之外,现在很少有应用程序真正需要关心 2038 年。 (2认同)

小智 11

日期时间与时间戳:

TIMESTAMP 用于跟踪记录的变化,并在每次记录发生变化时更新。

DATETIME 用于存储不受任何记录更改影响的特定和静态值。

TIMESTAMP 也受不同 TIME ZONE 相关设置的影响。DATETIME 是常数。

TIMESTAMP 在内部将当前时区转换为 UTC 进行存储,并在检索期间将其转换回当前时区。

DATETIME 不能这样做。

TIMESTAMP 为 4 个字节,DATETIME 为 8 个字节。

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?


Mar*_*llo 10

我发现TIMESTAMP能够在不使用不必要的触发器的情况下根据当前时间自动更新自身的能力无与伦比.这只是我,虽然TIMESTAMP是UTC,就像它说的那样.

它可以跟踪不同的时区,因此如果您需要显示相对时间,那么UTC时间就是您想要的.


ecl*_*eel 10

Timestamp和Datetime之间的另一个区别是在Timestamp中,您不能将默认值设置为NULL.

  • 这显然是错误的.[这是一个例子:](http://dev.mysql.com/doc/refman/5.1/en/timestamp-initialization.html)`CREATE TABLE t2(ts1 TIMESTAMP NULL,ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); `第一列可以接受NULL值. (8认同)

Pre*_*raj 10

+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
|                                       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.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)


Cha*_*iga 9

主要区别在于

  • 时间戳上的INDEX - 工作
  • 日期时间的INDEX - 不起作用

看看这篇文章,看看日期时间索引的问题

  • 如果您使用基于列值的函数进行选择,则两者都具有相同的问题,并且两者都可以编制索引. (6认同)
  • 索引适用于时间戳,在日期时间不起作用?你从那些帖子中得出了错误的结论. (4认同)

Acc*_*t م 8

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

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

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

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

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

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

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

简而言之

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

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


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


Han*_*ans 7

我更喜欢使用时间戳,以便将所有内容保存为一种通用的原始格式,并在PHP代码或SQL查询中格式化数据.在某些情况下,它会在您的代码中派上用场,以便在几秒钟内保留所有内容.


Mwa*_*iga 7

A TIMESTAMP需要4个字节,而a DATETIME需要8个字节.

  • “从 MySQL 5.6.4 开始,YEAR 和 DATE 的存储保持不变。但是......DATETIME 的打包效率更高,需要 5 个字节而不是 8 个字节”,因此时间戳和日期时间之间有 1 个字节的差异,时间戳“过期” 2038 年即将到来:)来自文档:https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html#data-types-storage-reqs-date-time (2认同)

use*_*220 6

我喜欢Unix时间戳,因为你可以转换为数字而只是担心数字.另外,你可以加/减并获得持续时间等.然后以任何格式将结果转换为日期.此代码查找文档的时间戳与当前时间之间经过的时间(以分钟为单位).

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

  • 或者,使用人类可重复和本机MySQL日期时间,并使用本机MySQL函数来添加/减去日期时间. (4认同)

Mah*_*ini 5

当您有来自不同国家的不同时区的访客时,TIMESTAMP很有用。您可以轻松地将TIMESTAMP转换为任何国家/地区的时区


Boo*_*boo 5

A 不DATETIME携带时区信息,并且将始终独立于会话有效的时区显示相同的时区,除非您明确更改它,否则默认为服务器的时区。但是,如果我DATETIME使用诸如 之类的函数NOW()而不是诸如 之类的文字来初始化列'2020-01-16 12:15:00',那么存储的值当然将是本地化到会话时区的当前日期和时间。

TIMESTAMP相比之下,A确实隐含地携带时区信息:当您TIMESTAMP用一个值初始化一个 列时,该值在存储之前被转换为 UTC。如果存储的值是文字,例如'2020-01-16 12:15:00',则出于转换目的,它会被解释为处于会话的当前时区中。相反,当TIMESTAMP显示一列时,它将首先从 UTC 转换为会话的当前时区。

何时使用其中之一?案例研究

一个社区剧团的网站正在展示它正在售票的戏剧的几场表演。这些表演的日期和时间将出现在一个下拉列表中,希望购买表演门票的客户可以从中选择一个。数据库列performance_date_and_time是一种DATETIME类型是有意义的。如果演出在纽约举行,则可以理解为涉及隐式时区(“纽约当地时间”),理想情况下,我们希望日期和时间显示为“2019 年 12 月 12 日晚上 8:00”无论会话的时区如何,也不必费心进行任何时区转换。

另一方面,一旦 2019 年 12 月 12 日晚上 8 点的表演开始,我们可能不再想为其出售门票,因此不再在下拉列表中显示该表演。因此,我们希望能够知道“2019-12-12 20:00:00”是否发生。这将争论有一个TIMESTAMP列,将会话的时区设置为“America/New_York”,set session time_zone='America/New_York'然后存储'2019-12-12 20:00:00'TIMESTAMP列中。从今以后,我们可以通过将此列与NOW()当前会话时区无关的列进行比较来测试性能是否已经开始。

或者,为了这两个不同的目的而使用 aDATETIME和 aTIMESTAMP列可能是有意义的。或不。显然,任何一种都可以达到两个目的。如果您只使用一DATETIME列,那么在与NOW(). 如果您只使用一TIMESTAMP列,则必须在显示该列之前将会话时区设置为您的本地时区。


归档时间:

查看次数:

840199 次

最近记录:

6 年,2 月 前