Установка значения времени и значения NULL с помощью Rose::DB::Object и MySQL
Я могу ошибаться здесь, но, похоже, здесь противоречивые стандарты.
MySQL рассматривает сохраненную дату и время "0000-00-00 00:00:00" как эквивалент NULL. (кажется, только для обновления, если datetime определено как 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 поля даты и времени (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 ответа
Вы должны быть в состоянии установить datetime
столбец к буквальному желаемому 0000-00-00 00:00:00
значение и сохранить его в базе данных:
$o->mycolumn('0000-00-00 00:00:00');
$o->save;
Такие "все ноль" значения не будут преобразованы в DateTime
объекты по Rose::DB::Object
, а скорее останутся как буквальные строки. Там нет смысла DateTime
объектный эквивалент для MySQL 0000-00-00 00:00:00
строки даты и времени.
Замечания: 0000-00-00
является действительным date
значение, но datetime
(или же timestamp
) значение должно включать время: 0000-00-00 00:00:00
Чтобы установить для столбца значение NULL, передайте undef
в качестве значения столбца:
$o->mycolumn(undef);
Конечно, если определение столбца в базе данных включает в себя NOT NULL
ограничение, save()
не сработает
MySQL позволяет типам даты быть неполными (без года, месяца и / или дня). '0000-00-00' - это действительная, не NULL дата MySQL. Почему вы думаете, что он соответствует 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