为什么 MySQL 不支持毫秒/微秒精度? [英] Why doesn't MySQL support millisecond / microsecond precision?

查看:35
本文介绍了为什么 MySQL 不支持毫秒/微秒精度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我刚刚发现了MySQL 中最令人沮丧的错误.

显然是 TIMESTAMP 字段和 支持函数不支持比秒更高的精度!?

Apparently the TIMESTAMP field, and supporting functions do not support any greater precision than seconds!?

所以我使用 PHP 和 Doctrine,我真的需要那些微秒(我使用的是 actAs: [Timestampable] 属性).

So I am using PHP and Doctrine, and I really need those microseconds (I am using the actAs: [Timestampable] property).

我发现我可以使用 BIGINT 字段来存储值.但是学说会增加毫秒吗?我认为它只是将 NOW() 分配给该字段.我还担心通过代码散布的日期操作函数(在 SQL 中)会中断.

I found a that I can use a BIGINT field to store the values. But will doctrine add the milliseconds? I think it just assigns NOW() to the field. I am also worried the date manipulation functions (in SQL) sprinkled through the code will break.

我还看到了一些关于编译 UDF 扩展的内容.这是不可接受的,因为我或未来的维护者会升级和 poof,更改消失了.

I also saw something about compiling a UDF extension. This is not an acceptable because I or a future maintainer will upgrade and poof, change gone.

有没有人找到合适的解决方法?

Has anyone found a suitable workaround?

推荐答案

我找到了解决方法!它非常干净,不需要任何应用程序代码更改.这适用于 Doctrine,也适用于其他 ORM.

I found a workaround! It is very clean and doesn't require any application code changes. This works for Doctrine, and can be applied to other ORM's as well.

基本上,将时间戳存储为字符串.

Basically, store the timestamp as a string.

如果日期字符串的格式正确,则比较和排序有效.当传递日期字符串时,MySQL 时间函数将截断微秒部分.如果 date_diff 等不需要微秒精度,这是可以的.

Comparisons and sorting works if the date string is formatted correctly. MySQL time functions will truncate the microsecond portion when passed a date string. This is okay if microsecond precision isn't needed for date_diff etc.

SELECT DATEDIFF('2010-04-04 17:24:42.000000','2010-04-04 17:24:42.999999');
> 0

SELECT microsecond('2010-04-04 17:24:42.021343');
> 21343 

我最终编写了一个 MicroTimestampable 类来实现它.我只是将我的字段注释为 actAs:MicroTimestampable,瞧,MySQL 和 Doctrine 的微时精度.

I ended up writing a MicroTimestampable class that will implement this. I just annotate my fields as actAs:MicroTimestampable and voila, microtime precision with MySQL and Doctrine.

Doctrine_Template_MicroTimestampable

class Doctrine_Template_MicroTimestampable extends Doctrine_Template_Timestampable
{
    /**
     * Array of Timestampable options
     *
     * @var string
     */
    protected $_options = array('created' =>  array('name'          =>  'created_at',
                                                    'alias'         =>  null,
                                                    'type'          =>  'string(30)',
                                                    'format'        =>  'Y-m-d H:i:s',
                                                    'disabled'      =>  false,
                                                    'expression'    =>  false,
                                                    'options'       =>  array('notnull' => true)),
                                'updated' =>  array('name'          =>  'updated_at',
                                                    'alias'         =>  null,
                                                    'type'          =>  'string(30)',
                                                    'format'        =>  'Y-m-d H:i:s',
                                                    'disabled'      =>  false,
                                                    'expression'    =>  false,
                                                    'onInsert'      =>  true,
                                                    'options'       =>  array('notnull' => true)));

    /**
     * Set table definition for Timestampable behavior
     *
     * @return void
     */
    public function setTableDefinition()
    {
        if ( ! $this->_options['created']['disabled']) {
            $name = $this->_options['created']['name'];
            if ($this->_options['created']['alias']) {
                $name .= ' as ' . $this->_options['created']['alias'];
            }
            $this->hasColumn($name, $this->_options['created']['type'], null, $this->_options['created']['options']);
        }

        if ( ! $this->_options['updated']['disabled']) {
            $name = $this->_options['updated']['name'];
            if ($this->_options['updated']['alias']) {
                $name .= ' as ' . $this->_options['updated']['alias'];
            }
            $this->hasColumn($name, $this->_options['updated']['type'], null, $this->_options['updated']['options']);
        }

        $this->addListener(new Doctrine_Template_Listener_MicroTimestampable($this->_options));
    }
}

Doctrine_Template_Listener_MicroTimestampable

class Doctrine_Template_Listener_MicroTimestampable extends Doctrine_Template_Listener_Timestampable
{
    protected $_options = array();

    /**
     * __construct
     *
     * @param string $options 
     * @return void
     */
    public function __construct(array $options)
    {
        $this->_options = $options;
    }

    /**
     * Gets the timestamp in the correct format based on the way the behavior is configured
     *
     * @param string $type 
     * @return void
     */
    public function getTimestamp($type, $conn = null)
    {
        $options = $this->_options[$type];

        if ($options['expression'] !== false && is_string($options['expression'])) {
            return new Doctrine_Expression($options['expression'], $conn);
        } else {
            if ($options['type'] == 'date') {
                return date($options['format'], time().".".microtime());
            } else if ($options['type'] == 'timestamp') {
                return date($options['format'], time().".".microtime());
            } else {
                return time().".".microtime();
            }
        }
    }
}

这篇关于为什么 MySQL 不支持毫秒/微秒精度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆