Сортировка Perl с Классом::DBI
У вас есть следующая таблица под названием Домашние животные:
name age pet
------------------------
Carol 25 null
Stean 23 cat
Mel 24 dog
Rich 24 rabbit
В базе данных MySQL на сервере mydbserver с пользователем "user" с паролем "password".
Сделайте следующее:
1) Создать Class::DBI
подключение к этой базе данных с вышеуказанными учетными данными (DBI.pm).
2) Создать класс для таблицы Pets (Pet.pm)
3) Создайте программу, которая печатает все имена людей в таблице "Домашние животные" и какого рода (если есть) питомца, которого он / она сортирует по имени, а затем по возрасту.
Вот код, который я написал.....
#!/usr/bin/perl
package Pet::DBI;
use DBI;
use strict;
use base 'Class::DBI';
Pet::DBI->set_db('Main','dbi:mysql:dname', 'user', 'password')
or die $DBI::errstr "\n";
1;
package Pet::Pets;
use base 'Pet::DBI';
use strict;
use warning;
Pet::Pets->table('Pets');
Pet::Pets->columns(All => qw/name age pet/);
1;
use Pet::Pets;
my @pets = Pet::Pets->retrieve_all;
for (sort {$a->name cmp $b->name} || {$a->age <=> $b->age} @Pets) {
print "Name:".$_->name ' => '."Age". $_->age"\n";
}
1;
1 ответ
Это в основном правильно, но есть ряд небольших проблем.
Нет необходимости загружать DBI, Class::DBI позаботится об этом за вас.
Вы должны использовать connection
вместо set_db("Main", ...)
, set_db
происходит от Ima::DBI, и это не вежливо (или необходимо) заглядывать под капот вот так.
Хотя это прямо не задокументировано в Class::DBI (так и должно быть), оно унаследовано от Ima::DBI, нет необходимости проверять ошибки DBI. RaiseError включен, и в случае сбоя соединения он выдаст ошибку.
У вас есть опечатка, use warning;
вместо use warnings;
,
Если вы не соединили три файла вместе для поста, если код находится в одном файле, 1;
заявления ничего не делают. use Pet::Pets
не будет работать, потому что нет Pet/Pets.pm
файл. Вам не нужно использовать класс, который уже находится в том же файле.
В общем, избегайте использования $_
если вам не нужно, слишком многие вещи могут спокойно использовать или изменить его. Вместо этого присвойте циклу for правильную переменную типа for my $person
,
sort
занимает всего один блок, но вы в основном правы. Так должно быть sort { ($a->name cmp $b->name) || ($a->age <=> $b->age) } @Pets
Чтобы избежать чтения всей, потенциально очень большой таблицы в память, сортировка должна выполняться в базе данных с ORDER BY name ASC, age ASC
и затем извлекал строку за раз, используя итератор. К сожалению, retrieve_all не поддерживает никаких опций. Ты можешь использовать retrieve_from_sql
добавить произвольный SQL в конец основного SELECT. my $all_people = Pet::Pets->retrieve_from_sql("ORDER BY name ASC, age ASC");
Тогда ваши данные уже будут отсортированы и могут быть прочитаны подряд. while( my $person = $all_people->next ) { ... }
Вы скучаете по .
в "Age". $_->age"\n"
,
Нулевые значения в базе данных возвращаются как undef. Вы хотите проверить, если $_->pet
определяется, и если не использовать какую-то другую строку, такую как "no pet"
или просто пустым ""
,
Вы печатаете возраст человека, вопрос задает его домашнее животное.
В противном случае это должно работать.
Но на самом деле, скажите, кто бы дал вам эту домашнюю работу, чтобы перестать говорить людям использовать Class::DBI. Они могут написать мне, если захотят, schwern@pobox.com.