• 締切済み

Perlで一覧表示

お世話になっております。 Perl初心者で、Java等は少し経験があります。 「検索を行い一覧を表示する」という画面をPerlで作成する際の 作り方について質問させてください。 現在は以下のような構成で画面を作っています。(DBアクセスには DBI を使用しています) ------------------------------ 【DAO的な pm】  引数として検索条件を受け取り、  DB にアクセスし、  $sth->fetchrow_arrayref で取り出した検索結果を  ハッシュや配列に詰めて返す 【画面の pl】 上記DAO的な pm を利用して検索結果を受け取り、 それをループで回して一覧として表示する ------------------------------ ただ、これだと配列にデータをため込むので 検索結果が多くなるとメモリをくいそうで気になっています。 (あと後述の方法と比べるとやっぱり遅い気がする…) 他の方が Perl で作った画面を見たところ、以下のような作り方を見かけました。 ------------------------------ 【画面の pl】 画面内で SQL を発行し、 $sth->fetchrow_arrayref で取り出した検索結果を 逐次出力していく ------------------------------ こちらのほうだと、一覧に出すものが多くても 上からパラパラ表示されていくので 閲覧者側のストレスも少ないと思ったのですが、 Perlの作りとしてはこういうほうが一般的なのでしょうか。 なんとなくDBアクセスは汎用的なクラスにしてしまいたい気持ちになるのですが Perlではあんまりそういうことはしない、とかPerlでもするよ、とか ご存じの方がいらっしゃいましたら教えてください。 あとは関数の戻り値として検索結果をごそっと返すのではなくて、 関数の引数として「一件分のデータを受け取るDelegate」を渡してみたらどうだろうかとか思っているのですが 変でしょうか… よろしくお願いします。

  • aki04
  • お礼率76% (30/39)
  • Perl
  • 回答数1
  • ありがとう数1

みんなの回答

  • t-okura
  • ベストアンサー率75% (253/335)
回答No.1

最近は、よほど単純なウェブページを作るのでなければ、HTML::Template や Template Toolkit のようなテンプレートエンジンを使い、ページの元になるテンプレートとそこに埋め込む変数の組み合わせでページを作ります。 テンプレートエンジンに繰り返しデータを渡す際は配列にするので、fetchrow_arrayref で一行ずつデータを取り出しても、サブルーチンでまとめて取り出しても同じことだと思います。 パラパラと表示ということでは、ウェブサーバは出力データをバッファリングしてブラウザに返すので、よほど長大なページでないかぎり目立った違いはないと思いますし、そんな長大なページは見たくない(ページ分割して欲しい)でしょう。 メモリについても、DBI は SELECT を実行したときにデータベースからデータを取り出します。fetchrow_arraref ではすでにバッファに取り込まれたデータを参照しているだけなので、大きな差はでないはずです。 まとめて取り込めないくらいデータが多い場合は、SELECT LIMIT OFFSET で一度に取得するデータを制限し、OFFSET をずらしながら順次データを処理することになります。そしてその時は LIMIT や OFFSET を意識しなくてもよいよう > 「一件分のデータを受け取るDelegate」 のようなサブルーチンを用意するとよいと思います。

aki04
質問者

お礼

回答ありがとうございます。 大変参考になります。 やっぱりテンプレートを使って view と model を分離させるのってPerlでもやるんですね。 # もともと既存画面があり、 # 私は追加画面を作成しているのですが # 既存画面がそういうふうにはなっていないので… Perlのことを聞ける人が周りにいないのでとても助かります。 ありがとうございます。 今回は表示する行数はさほど多くはないのですが、 データがあちこちに散っていて、 ---------------------------------------- DBサーバA のテーブルに対して SELECT foreach (検索結果) {   検索結果の id をキーに DBサーバB のテーブルに対して SELECT   配列に溜める } 配列を返す ---------------------------------------- のようなことをしていてデータを全件取ってくるのが若干遅めです。 # 別のシステムでも使われているテーブルを参照しているので # DB の見直しもむずかしくて… テンプレートエンジンを使っている場合は配列で渡すしかなさそうですが、 今回は幸か不幸かそうではないので 一行取り出して表示、一行分取り出して... にしてみようかと思っています。 「一件分のデータを受け取るDelegate」のパタンをさっきちょっと実験してみたので。 …実験してみたソースを貼りたかったのですが長すぎて貼れませんでした。 前後をはしょるのでわからないかもしれませんが一応貼るだけ貼ってみます。 ------------------------------ ### 今まで自分で書いてた感じ   # 取得   my @lst = &DummyDAO::get_list;   # 出力   print $header;   foreach my $row (@lst) {     &view_row($row);   }   print $footer; ------------------------------ ### 既存画面の書かれ方。 ### 表示の体感速度は速い、でもあんまり好きじゃない   print $header;   for (my $r = 1; $r <= $row_count; $r++) {     sleep($sleep_ms);     # 取得dummy     my $row = {};     for(my $c = 1; $c <= $col_count; $c++) {       $row->{$c} = sprintf("%05d", $r);     }     # 出力     &view_row($row);   }   print $footer; ------------------------------ ### こうしてみようかなと思ってる ### 表示の体感速度は既存画面と同じぐらい?   print $header;   # 関数のリファレンスを渡す   &DummyDAO::get_list2(\&view_row);   print $footer; ------------------------------ ちゃんとテンプレートエンジンを使う場合は使えなさそうですが 今回はこれで良いかな…? と… ありがとうございました。

関連するQ&A

  • PerlでMySQLのテーブル一覧取得

    PerlでMySQLのデータベース内のテーブル一覧を取得することはできますか? 自分で以下の様なサブルーチンを作りましたが、返り値に何も入っていませんでした。 コマンドラインでもshow tables;で確認したのでテーブルは確実に存在します。 接続も showでfetchrow_arrayなどは使えないのでしょうか? またselect文でテーブル一覧を取得する方法がありましょうか? Error: failed to connect to DB.とは出てこないので、接続も成功しています。 sub mysql_tablesGet{ my @data=@_; my $db_id = $data[0]; my $db_password = $data[1]; my $dbh = DBI->connect("dbi:mysql:dbname=".$ftp_id.";host=$mysql_host", $db_id,$db_password) or die "$!\n Error: failed to connect to DB.\n"; my $sth = $dbh->prepare("show tables;"); $sth->execute; my @response; my $i=0; while(my @var = $sth->fetchrow_array){ my ($table_name) = $var[0]; $response[$i] = $table_name; $i++; } $dbh->disconnect; return @response; } MySQLのログはこんなのが出ています。 130406 17:11:44 70 Connect test2@192.168.11.22 on test2 70 Query set autocommit=1 特にエラーは出ていないので、show tables;は成功していると思います。

    • ベストアンサー
    • Perl
  • mysqlのデータをperlで読み込んで????を表示される

    過去にもあった質問なのですが、アドバイスお願いします。 perlからmysqlにアクセスしてデータを読み込むと日本語が「??????」と表示されます。 バージョンは下の通りです。 perl:ActivePerl-5.8.8.820-MSWin32-x86-274739 mysql:5.0 OS:windowsXP mysqlの文字コードはstatusで確かめました。 mysql> status; -------------- mysql Ver 14.12 Distrib 5.0.27, for Win32 (ia32) Connection id: 74 Current database: Current user: ******@localhost SSL: Not in use Using delimiter: ; Server version: 5.0.27-community-nt Protocol version: 10 Connection: localhost via TCP/IP Server characterset: sjis Db characterset: sjis Client characterset: sjis Conn. characterset: sjis TCP port: 3306 Uptime: 3 hours 39 min 2 sec Threads: 1 Questions: 232 Slow queries: 0 Opens: 26 Flush tables: 1 Open ta bles: 0 Queries per second avg: 0.018 -------------- mysql> SELECT * FROM table1 と打てば、日本語は表示されます。 perlのコードのコードを書きます。 #!C:/usr/local/Perl/bin/perl print "Content-type: text/html;charset=Shift_JIS\n\n"; use DBI; $user = '***'; $passwd = '***'; $sql="SELECT * FROM categ"; ----略(HTMLタグ)------ $db = DBI->connect('DBI:mysql:board:localhost', $user, $passwd); $sth = $db->prepare($sql); $sth->execute; $num_rows = $sth->rows; $categ_num=$num_rows; for ($i=0; $i<$num_rows; $i++) { @a = $sth->fetchrow_array; print"$a[0] $a[1]<br>"; } $sth->finish; $db->disconnect; ----略(HTMLタグ)------ 結果 0 ????? 1 ????? ブラウザで文字の種類を変えても「?????」のままです。 mysqlのテーブルから取り出した値をjcode.plで変換しても変わらないようです。 &jcode::convert(\$categ[$i], "sjis"); print"<tr><td>no:$i $categ[$i] </td></tr>"; まだ、設定の足りないところがあるのでしょうか。 アドバイスお願いします。

    • ベストアンサー
    • MySQL
  • unixのperlで

    UNIXのPerlでは引数は@ARGVに入ると思うのですが、 a.pl *.c "*.c" という引数を入れるとファイルが展開されそのフォルダの中の "12-1.c" とか "12-2.c" とかいう引数が、配列に1つずつ入ってきました。 引数の文字列を何の修正もなしに(できればスペースも)受け取る方法はないですか?

    • ベストアンサー
    • Perl
  • 配列に入った変数を二度使いたい

    perlでDBデータをセレクトし表示させるプログラムで 以下のように一回目のforループでは正常に表示されます。 二度目に表示させようとすると何もデータがなくなっているようです。 print でも、もちろんなにも表示しません。 配列名を変えてもだめでした。とこが原因なのかわかりません。 ステートメントハンドルとかが関係あるのでしょうか? いろいろ調べたのですが、ちょっとわかりませんでした。 申し訳ないのですが、教えてください。 話をまとめるとDBからセレクトした同じ行のデータを2回表示させたいということです。 よろしくお願いします。 my $db = DBI->connect("DBI:Pg:dbname=$UDBNAME",$USERNAME,$USERPASS); my $sth=$db->prepare(" select * from server where no = $no "); $sth->execute; #一回目 for ((my $count)=0; $count<$num_rows;$count++){ my @ar=$sth->fetchrow_array; #二回目 for ((my $count)=0; $count<$num_rows;$count++){ my @ar=$sth->fetchrow_array;

    • ベストアンサー
    • Perl
  • perlでdb(mysql)に接続

    perlでdb(mysql)に接続し、取得したデータを 表示させるというようなことをしたいのですが、うまく いきません。 ファイル名test.cgi mysqlのバージョンは 5.0.45で 記述は以下です。 #!/usr/bin/perl use DBI; my $dbh = DBI->connect("DBI:mysql:database, "userid", "password"); my $sth = $dbh->prepare('SELECT * FROM tablename'); $sth->execute; print "Content-Type: text/plain\n\n"; print "\n"; while(my @row = $sth->fetchrow_array) { print "$row[0]:$row[1]\n"; } $sth->finish(); $dbh->disconnect(); exit; ブラウザで確認すると何も表示されず、ログとして 以下のエラーが確認できます。 DBD::mysql::st execute failed: Table 'database.tablename' doesn't exist at test.cgi line 8. DBD::mysql::st fetchrow_array failed: fetch() without execute() at test.cgi line 11. my $sth = $dbh->prepare('SELECT * FROM tablename'); で指定したテーブルは存在しておりますし、SQL文の記述も 問題ないと思われます。 また、ファイルのパーミッションは705(755でも同様の結果)です。 perl初心者のため、どこが問題なのか検討がつきません。 ご助言いただきたく存じます。 よろしくお願いいたします!

    • ベストアンサー
    • Perl
  • Perl(cgi)からPerl(cgi)への引数

    (1)Perl(cgi)から(2)Perl(cgi)へ引数(データ)を渡す方法を教えてください。 プログラムの流れとしましては、 (1):データベースを検索&該当結果の番号をリンクで表示 (2):(1)でクリックしたリンクと対応する結果を表示 となっております。 また、セキュリティの事を考えて「POST」で送りたいと考えています。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • perlでmysqlに接続

    初歩的な質問で申し訳ありません。 perlでmysqlに接続できず困っています(OSはWindowsXPです)。 バージョンは下の通りです。 perl : ActivePerl-5.8.8.820-MSWin32-x86-274739 mysql : MySQL Server 5.0 DOSでppmを入力すると「perl package manager」というウィンドウが立ち上がり、「DBD-SQLite」と「DBI」をインストールすることができました。 サンプルコードは下の通りです。 #!C:/usr/local/Perl/bin/perl use DBI; $user = '*****'; $passwd = '*****'; $db = DBI->connect('DBI:mysql:bulletin_board:localhost', $user, $passwd); $sth = $db->prepare("SELECT * FROM data"); $sth->execute; $num_rows = $sth->rows; print "該当 $num_rows 件\n"; for ($i=0; $i<$num_rows; $i++) { @a = $sth->fetchrow_array; print "no=$a[0], title=$a[1] name=$a[2] \n"; } $sth->finish; $db->disconnect; DOSで実行すると C:\Program Files\War-ftpd\FTPRoot\usr\f-taka\cgi-bin>perl sqlTest.cgi install_driver(mysql) failed: Can't locate DBD/mysql.pm in @INC (@INC contains: C:/usr/local/Perl/site/lib C:/usr/local/Perl/lib .) at (eval 4) line 3. Perhaps the DBD::mysql perl module hasn't been fully installed, or perhaps the capitalisation of 'mysql' isn't right. Available drivers: DBM, ExampleP, File, Gofer, Proxy, SQLite, Sponge. at sqlTest.cgi line 8 というエラーが出ました。原因は何なのでしょうか。 MySQL側で設定することはあるのでしょうか。 アドバイスお願いします。

    • ベストアンサー
    • Perl
  • PerlでDBIを使いますが、結果セットをフィールド名でアクセスするには?

    OSはWindowsでAccess2002のデータベースをODBC経由でDBIを用いて、Perlからアクセスします。 以下のように、結果セットをフィールド名でアクセスしたいです。 可能でしょうか? #!/perl/bin/perl #!/usr/bin/perl -w use DBI; # create the DSN connection $dsn = "dbi:odbc:test"; $dbh = DBI->connect($dsn) or die "接続エラー"; $query = "select * from goods;"; # execute the query $sth = $dbh->prepare($query); $sth->execute(); print "no name price\n"; print "--------------------------------------\n"; while(@item = $sth-> fetchrow) { #print "@item[0] @item[1] @item[2]"; #----- 通常はこうだが、 print "$item{'goods_name'} $item{'goods_price'} $item{'auto_no'}"; #----こんな感じで利用したい。 print ("\n"); } # disconnect $sth->finish(); $dbh->disconnect(); exit; __END__

    • ベストアンサー
    • CGI
  • PerlでSQLiteを使おうとしてもうまく行きません

    下記のような感じでPerlプログラムからSQLiteのデータベースから読み出すプログラムを組んでみました。 もちろん、実際にデータベースのファイルを作ってあります。 下のように、かなりシンプルで簡単なプログラムですし、 間違ってもいないとは思うのですが・・・ use DBI; $db = DBI->connect("dbi:SQLite:dbname=accountdb","","",); $sth = $db->prepare("SELECT * FROM user"); $sth->execute;#結果を取得しresに代入 print "$sth\n"; $sth->finish; exit; 上を実行した結果は、下記の通りです。 DBI::st=HASH(0x32706c4) closing dbh with active statement handles during global destruction. 私が思うに、データが$sthに帰って来ると思うのですが、 実際にはDBI::st=HASH(*****)のようなものしかかえってきません アドバイスをどうか宜しく御願いします (別カテゴリで似たような質問をさせていただきましたが、これはまた別です・・・)

  • データベースから取得したデータを配列に格納

    データベースから取得したデータを配列に格納することができません。 唯一、以下の方法で格納できたのですが、この場合データベースの項目の数が、あらかじめ分かっている場合にしか使用できません。googleで検索して出てくるサンプルは全てループ内でprintしているので参考になりませんでした。 やりたいことは単純で、データベースにクエリーを発行した結果の複数レコードをそのまま配列に格納することです。perlに詳しい方がおられましたらよろしくお願いします。 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ■データベース内のデータ id=1,subid=1,data1=aaa id=1,subid=2,data1=bbb id=1,subid=3,data1=ccc ■期待する結果 @result = ("1","1","aaa", "1","2","bbb", "1","3","ccc", ) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ■実際のソース ********************************************************** use DBI; #//■DB接続 $db = DBI->connect("DBI:mysql:$DbName:$DbHost", $DbUser, $DbPass); $sth = $db->prepare($sql); $sth->execute; $cnt = $sth->rows; for($i=0; $i<$cnt; $i++){ @work = $sth->fetchrow_array; @result[$i] = ([$work[0],$work[1],$work[2],]); } #//■CLOSE $sth->finish; $db->disconnect; for($i=0; $i<$cnt; $i++){ print "<p>".$result[$i][0]."/".$result[$i][1]."/".$result[$i][2]."</p>\n"; } **********************************************************

    • ベストアンサー
    • Perl

専門家に質問してみよう