【问题标题】:Sorting Perl with Class::DBI使用 Class::DBI 对 Perl 进行排序
【发布时间】:2015-03-17 01:27:23
【问题描述】:

您有一个名为 Pets 的表格:

name     age     pet
------------------------
Carol     25     null
Stean     23     cat
Mel       24     dog
Rich      24     rabbit

在服务器 mydbserver 上的 MySQL 数据库中,用户为 'user' “密码”的密码。

执行以下操作:

1) 使用上述凭据 (DBI.pm) 创建到此数据库的 Class::DBI 连接。

2) 为表 Pets ( Pet.pm ) 创建一个类

3) 创建一个程序,打印 Pets 表中所有人的姓名以及种类(如果有) 他/她按名称然后年龄排序的宠物。

这是我写的代码.....

#!/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;

【问题讨论】:

  • 如果可能,请考虑DBIx::Class。 Class::DBI 不再维护,按照现代标准,它不是一个很好的 ORM。我应该知道,I wrote it。还有,这是作业吗?如果是,请让老师知道作者说停止使用 Class::DBI。 :) 最后,Class::DBI 文档已经包含an example of doing exactly this
  • 谢谢,不幸的是他们坚持使用 Class::DBI 而不是 DBIx::Class 应用程序使用它。
  • 我想知道第3个问题的答案。我得到了前 2 个问题。
  • “他们”是谁?他们为什么坚持使用受支持的软件?这听起来不是个好建议?
  • @Dave Cross 我同意,但是您如何看待使用 Class::dbi 进行排序?

标签: perl class-dbi


【解决方案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-&gt;name cmp $b-&gt;name) || ($a-&gt;age &lt;=&gt; $b-&gt;age) } @Pets

为避免将整个可能非常大的表读入内存,排序实际上应该在数据库中使用ORDER BY name ASC, age ASC 完成,然后使用iterator 一次检索一行。不幸的是,retrieve_all 不支持任何选项。您可以使用retrieve_from_sql 将任意 SQL 添加到基本 SELECT 的末尾。 my $all_people = Pet::Pets-&gt;retrieve_from_sql("ORDER BY name ASC, age ASC"); 这样你的数据就已经排序好了,可以一次读取一行。 while( my $person = $all_people-&gt;next ) { ... }

您在"Age". $_-&gt;age"\n" 中缺少.

数据库中的空值返回为 undef。您需要检查 $_-&gt;pet 是否已定义,如果不使用其他字符串,如 "no pet" 或只是空白 ""

您正在打印此人的年龄,该问题询问他们的宠物。

否则,它应该可以工作。

但是说真的,告诉给你这个作业的人不要再告诉人们使用 Class::DBI。如果他们愿意,他们可以给我发电子邮件,schwern@pobox.com。

【讨论】:

  • 谢谢 Schwern,排序问题让我很困惑,你怎么能对宠物主人的名字进行排序,然后按年龄排序?不是一个优先于另一个而失去秩序吗?使用它的实体也是你的类的忠实粉丝::dbi!
  • @user_falafel 我现在在您的排序调用中看到了错误。你基本上是正确的,但是语法是错误的。我已经编辑了我的答案。如果该实体是一个超级粉丝,那么他们会尊重我的要求,停止教人们使用它。它不再是一个有用的现实世界 ORM,它不再被维护,并教给一些坏习惯。例如,将整个表加载到内存中,因为无法将排序选项传递给retrieve_all。
  • 我找到了一种更好的方法来检索所有带有 ORDER BY 的行。
  • 我确实使用迭代器和下一个方法在名称上使用了 ASC 的顺序,但他们不喜欢答案并希望我不使用迭代器。所以,我决定使用数组,检索并存储所有行,然后在 ASC 中对对象进行排序并打印出来。
  • @user_falafel 你说对了。 retrieve_all 基本上不应该被使用,并且尽可能使用迭代器。除非您知道您将只取回有限的数据集,例如使用 LIMIT 子句,否则您永远不应该一次从数据库中获取所有行。它可能会消耗您的所有内存,并使您容易受到 DOS 攻击。他们正在教你在过时的 ORM 上的不良做法,我希望你不要付太多钱。我有兴趣查看课程材料并对其进行评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
相关资源
最近更新 更多