Byr*_*ock 41 php mysql doctrine
所以我发现了MySQL中最令人沮丧的错误.
显然,TIMESTAMP现场和支持功能不支持比秒更精确!?
所以我使用PHP和Doctrine,我真的需要那些微秒(我正在使用该actAs: [Timestampable]属性).
我发现我可以使用BIGINT字段来存储值.但是教条会加几毫秒吗?我认为它只是将NOW()赋予该领域.我也担心通过代码散布的日期操作函数(在SQL中)会破坏.
我还看到了有关编译UDF扩展的一些内容.这是不可接受的,因为我或未来的维护者将升级和噗,改变了.
有没有人找到合适的解决方法?
Xav*_*ois 36
有关下一位读者的信息,最终将在5.6.4版本中更正此错误:
"MySQL现在支持TIME,DATETIME和TIMESTAMP值的小数秒,精度高达微秒."
Mic*_*zka 29
从SQL92标准:
- TIMESTAMP - 包含日期时间字段的年,月,日,小时,分钟和秒.
从我的角度来看,符合SQL92的数据库不需要支持毫秒或微秒.因此Bug#8523被正确标记为"功能请求".
Doctrine如何处理微秒等?我刚刚发现以下内容: Doctrine #Timestamp:
时间戳数据类型仅仅是日期和时间数据类型的组合.时间戳类型的值的表示是通过将日期和时间字符串值连接在由空格连接的单个字符串中来完成的.因此,格式模板是YYYY-MM-DD HH:MI:SS.
因此,在SQL92-docs中也没有提到微秒.但我不是深入学说,但它似乎是一个像java中的hibernate之类的ORM.因此,可以/应该可以定义您自己的模型,您可以将时间信息存储在BIGINT或STRING中,并且您的模型负责将其相应地读/写到PHP类中.
顺便说一句:我不认为MySQL会在不久的将来(如未来5年)以毫秒/微秒的速度支持TIMESTAMP.
我找到了解决方法!它非常干净,不需要更改任何应用程序代码.这适用于Doctrine,也可以应用于其他ORM.
基本上,将时间戳存储为字符串.
如果日期字符串格式正确,则比较和排序有效.MySQL时间函数将在传递日期字符串时截断微秒部分.如果不需要微秒精度,这是可以的date_diff.
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
Run Code Online (Sandbox Code Playgroud)
我最后写了一个MicroTimestampable实现这个的类.我只是注释我的字段,actAs:MicroTimestampable并且使用MySQL和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));
}
}
Run Code Online (Sandbox Code Playgroud)
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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)