Neden MySQL desteği milisaniye / mikrosaniye hassasiyet mi?

6 Cevap php

Yani sadece bulundu the most frustrating bug ever in MySQL.

Görünüşe TIMESTAMP alanı, ve supporting functions saniyeden daha herhangi bir büyük hassasiyet desteği yok!?

Yani PHP ve Doktrini kullanıyorum, ve ben gerçekten (I actAs: [Timestampable] özelliğini kullanıyorum) bu mikrosaniye gerekir.

Ben değerleri saklamak için BIGINT alanını kullanabileceğiniz bir bulduk. Ama irade doktrini milisaniye eklemek? Ben sadece alanına () ŞİMDİ atar düşünüyorum. Ben de tarih işleme kodu ile serpilir (SQL) fonksiyonlarını kıracak endişe duyuyorum.

Ben de bir UDF uzantısı derleme hakkında bir şey gördüm. Ben ya da bir gelecek sürdürme yükseltme ve puf, değişim gitti çünkü bu kabul edilebilir değildir.

Herkes uygun bir çözüm buldu?

6 Cevap

Ben bir çözüm buldum! Çok temiz ve herhangi bir uygulama kod değişikliği gerektirmez. Bu Doktrin için çalışıyor, ve de diğer ORM en uygulanabilir.

Temel olarak, bir dize olarak damgası saklayın.

Karşılaştırmalar ve tarih dize doğru biçimlendirilmiş ise işler sıralama. Bir tarih dizesi geçtiğinde MySQL zaman fonksiyonları mikrosaniye kısmını keser. Mikrosaniye hassas date_diff vb için gerekli değilse, bu tamam

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 

Ben bu uygulayacak bir MicroTimestampable sınıf yazma sona erdi. Ben sadece actAs:MicroTimestampable ve voila, MySQL ve Doktrini ile microtime hassas olarak benim alanları açıklama.

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();
            }
        }
    }
}

: SQL92-Standard gelen

  • TIMESTAMP - contains the datetime field's YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND.

Bir SQL92 uyumlu veritabanı benim açımdan mili-ya da mikrosaniye desteklemek gerekmez. Bu nedenle Hata # 8523 doğru "özelliği isteği" olarak işaretlenir.

How does Doctrine will handle microseconds et al? I just found the following: Doctrine#Timestamp:

The timestamp data type is a mere combination of the date and the time of the day data types. The representation of values of the time stamp type is accomplished by joining the date and time string values in a single string joined by a space. Therefore, the format template is YYYY-MM-DD HH:MI:SS.

So there are no microseconds mentioned either as in the SQL92-docs. But I am not to deep into doctrine, but it seems to be an ORM like hibernate in java for example. Therefore it could/should be possible to define your own models, where you can store the timeinformation in a BIGINT or STRING and your model is responsible to read/write it accordingly into your PHP-classes.

BTW: MySQL önümüzdeki 5 yıl örneğin yakın gelecekte mili / mikrosaniye ZAMAN destek beklemeyin.

Sonraki okuyucular için bilgi için, bu hata sonunda sürümünde düzeltilecektir olan 5.6.4:

"MySQL şimdi mikrosaniye hassasiyetle kadar ile, TIME, DATETIME ve TIMESTAMP değerleri kesirli saniye destekler."

Veri depolamak için Doktrini kullanıyorsanız, ve Doktrin, fraksiyonel saniye desteklemiyor gibi o darboğaz MySQL değildir.

Ben size ekstra hassasiyet ihtiyacınız nesneleri ek alanları tanımlamak ve onlara microtime() çıkışını saklamak öneririz. Dönem saniye damgası için tek ve mikrosaniye bölümü için diğer - muhtemelen iki farklı alanlarda saklamak istiyorum. Standart 32bit tamsayıları depolamak ve kolayca sıralamak ve SQL kullanarak onlara filtre edebilirsiniz.

Genellikle işlemek ve yerel saat türleri ile biniyorlar ve uluslararası hizmet veren tutmak bütün zaman dilimi sorunu önlemek için daha kolay olduğu gibi sık sık yerine yerli damgası türleri çağı Saniye saklanmasını tavsiye ederiz.

Milisaniye cinsinden Time için başka bir geçici çözüm. Oluşturulma fonksiyonu "time_in_msec"

KULLANIM:

Milisaniye iki tarih arasındaki fark.

mysql> SELECT time_in_msec('2010-07-12 23:14:36.233','2010-07-11 23:04:00.000') AS miliseconds;
+-------------+
| miliseconds |
+-------------+
| 87036233    |
+-------------+
1 row in set, 2 warnings (0.00 sec)



DELIMITER $$

DROP FUNCTION IF EXISTS `time_in_msec`$$

CREATE FUNCTION `time_in_msec`(ftime VARCHAR(23),stime VARCHAR(23)) RETURNS VARCHAR(30) CHARSET latin1
BEGIN
    DECLARE msec INT DEFAULT 0;
    DECLARE sftime,sstime VARCHAR(27);
    SET ftime=CONCAT(ftime,'000');
    SET stime=CONCAT(stime,'000');
    SET  msec=TIME_TO_SEC(TIMEDIFF(ftime,stime))*1000+TRUNCATE(MICROSECOND(TIMEDIFF(ftime,stime))/1000,0);
    RETURN msec;
END$$

DELIMITER ;

MySQL sürüm 5.6.4 yılından itibaren, bir sütunda mikrosaniye saklar.

"MySQL şimdi mikrosaniye hassasiyetle kadar ile, TIME, DATETIME ve TIMESTAMP değerleri kesirli saniye destekler."

Örneğin:

CREATE TABLE `test_table` (
`name` VARCHAR(1000) ,
`orderdate` DATETIME(6)
);

INSERT INTO test_table VALUES('A','2010-12-10 14:12:09.019473');

SELECT * FROM test_table;

Sadece datetime (6) için datetime veri türünü değiştirmek gerekir;

For more information refer following: http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html