Сортировка 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.

Другие вопросы по тегам