Установка значения времени и значения NULL с помощью Rose :: DB :: Object и MySQL - PullRequest
3 голосов
/ 27 января 2010

Я могу ошибаться, но, похоже, здесь противоречивые стандарты.

MySQL рассматривает сохраненную дату и время «0000-00-00 00:00:00» как эквивалент NULL. (похоже, только для обновления, если дата и время определены как NOT NULL)

Но Rose :: DB :: Object использует DateTime для полей MySQL DATETIME, и при попытке установить нулевое значение DATETIME из «0000-00-00» вызывает исключение в модуле DateTime. т.е. я не могу создать объект DateTime с годом 0, месяц 0, день 0, потому что это вызывает исключение в модуле DateTime.

Я проверил в Rose :: DB :: Object :: Metadata :: Column :: Datetime и не вижу способа явной обработки NULL DateTime при создании записи или получении.

Я что-то упустил?

т. Е. Может ли Rose :: DB :: Object обрабатывать поля NULL datetime (MySQL), хотя DateTime (модуль Perl) не может.

Пример кода:

#!/usr/bin/perl
use strict;
use warnings;
use lib 'lib';
use RoseDB::dt_test;

my $dt_entry =  RoseDB::dt_test->new();
$dt_entry->date_time_field('0000-00-00');
$dt_entry->save;



1;

__END__
# definition of table as stored in DB

mysql> show create table dt_test \G
*************************** 1. row ***************************
       Table: dt_test
Create Table: CREATE TABLE `dt_test` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `date_time_field` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

с модулем RoseDB :: dt_test:

package RoseDB::dt_test;
use strict;
use warnings;

# this module builds up our DB connection and initializes the connection through:
# __PACKAGE__->register_db
use RoseDB;

use base qw(Rose::DB::Object);

__PACKAGE__->meta->setup (
    table => 'dt_test',

    columns =>
    [
      id              => { type => 'int', primary_key => 1 },
      date_time_field => { type => 'datetime' },
    ],
);

sub init_db { RoseDB->get_dbh }

1;

Когда я запускаю его, я получаю сообщение об ошибке «Неверное значение даты и времени:« 0000-00-00 »в строке tmp.pl 8»

Когда я меняю дату на «2010-01-01», она работает как положено:

mysql> select * from dt_test\G
*************************** 1. row ***************************
             id: 1
date_time_field: 2010-01-01 00:00:00

Мне наконец-то удалось воссоздать пример запроса NULL MySQL!

mysql> create table dt_test(dt_test_field datetime not null);
Query OK, 0 rows affected (0.05 sec)

mysql> insert into dt_test values(null);
ERROR 1048 (23000): Column 'dt_test_field' cannot be null
mysql> insert into dt_test values('0000-00-00');
Query OK, 1 row affected (0.00 sec)

mysql> select * from dt_test;
+---------------------+
| dt_test_field       |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)

mysql> select * from dt_test where dt_test_field is null;
+---------------------+
| dt_test_field       |
+---------------------+
| 0000-00-00 00:00:00 |
+---------------------+
1 row in set (0.00 sec)

Похоже, в определениях таблиц, где datetime определены с помощью NOT NULL, а затем попытка использовать MySQL "fake null", является проблемой. Я слишком устал играть с этим сейчас, но я посмотрю, что произойдет, когда я изменю структуру стола утром.

Ответы [ 2 ]

4 голосов
/ 27 января 2010

Вы сможете установить для столбца datetime желаемое буквальное значение 0000-00-00 00:00:00 и сохранить его в базе данных:

$o->mycolumn('0000-00-00 00:00:00');
$o->save;

Такие "все нулевые" значения не будут преобразованы в DateTime объекты на Rose::DB::Object, а скорее останутся в виде буквенных строк. Не существует семантического DateTime эквивалентного объекта для строк 0000-00-00 00:00:00 даты и времени MySQL.

Примечание: 0000-00-00 является действительным значением date, но значение datetime (или timestamp) должно включать время: 0000-00-00 00:00:00

Чтобы установить для столбца значение NULL, передайте undef в качестве значения столбца:

$o->mycolumn(undef);

Конечно, если определение столбца в базе данных включает ограничение NOT NULL, save() не будет работать.

1 голос
/ 27 января 2010

MySQL позволяет типам даты быть неполными (без года, месяца и / или дня). '0000-00-00' - это действительная, не равная NULL дата MySQL. Как вы думаете, почему он соответствует IS NULL?

$ echo "select date('0000-00-00') is null" | mysql
date('0000-00-00') is null
0

Для сравнения:

$ echo "select date('0000-00-32') is null" | mysql
date('0000-00-32') is null
1
...