【问题标题】:Using UNIX_TIMESTAMP in a virtual (calculate) column in MariaDB / MySql在 MariaDB / MySql 的虚拟(计算)列中使用 UNIX_TIMESTAMP
【发布时间】:2017-04-02 09:56:40
【问题描述】:

我正在尝试创建一个包含时间戳列和虚拟(计算)列的表,该列包含一个帮助键,用于对具有同一小时时间戳的行进行分组。为此,我在 MariaDB / MySql 中使用以下命令:

CREATE TABLE mytable(t TIMESTAMP, u INT AS (UNIX_TIMESTAMP(t) DIV 3600);

返回以下错误:

ERROR 1901 (HY000): Function or expression is not allowed for column 'u'

根据文档,我看不出这不起作用的原因。有什么想法吗?

【问题讨论】:

    标签: mysql mariadb unix-timestamp calculated-columns virtual-column


    【解决方案1】:

    替换这个...

    (UNIX_TIMESTAMP(t) DIV 3600)
    

    ...用这个...

    (TIMESTAMPDIFF(HOUR,'1970-01-01 00:00:00',t))
    

    已在 MariaDB 10.1.14 上验证,这应该适用于任何更高版本。

    由于1970-01-01 00:00:00UNIX_TIMESTAMP() 中的0,并且DIV 3600 是整数除法,因此您的表达式似乎等于自1970-01-01 00:00:00 以来的小时数的FLOOR() ... 和 TIMESTAMPDIFF() 似乎提供了相同的值。

    MariaDB 似乎将UNIX_TIMESTAMP() 视为非确定性的,这在提供参数时是不正确的。 MySQL 核心可能缺乏“有时是确定性”考虑内置函数的能力,或者这可能是一个错误。

    但我相信你有一个使用TIMESTAMPDIFF() 的可行解决方法。

    另请注意,您似乎需要 PERSISTENT 关键字,否则无法索引虚拟列,因为该值未存储。

    ERROR 1901: Key/Index cannot be defined on a non-stored computed column
    

    【讨论】:

    • 我相信这段代码没有考虑到客户的时区。因此,它可以在不同的客户端获得不同的值。
    • 这无法解决,因为限制是它不能依赖于行外的数据(如客户端时区) - 请参阅mariadb.com/kb/en/library/generated-columns/#limitations。我发现的唯一 hack 是客户端是否在您的完全控制之下并使用稳定的 TZ。然后,您可以添加具有t 时当前的偏移量(在您的情况下以小时为单位)的列。然后可以在 (TIMESTAMPDIFF(HOUR, '1970-01-01', t) - t_tz_offset) 之类的计算中使用此列...但正如我之前所说的,它是超级丑陋的 hack
    • @chipiik 是的,是的。我可能忽略了这一点,因为我很少在 UTC 之外处理会话。
    猜你喜欢
    • 2020-11-13
    • 2013-02-18
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多