• ベストアンサー

SQL構文でカラム名をハッシュのキーに

PerlをDBIでMySQLに接続しています。 MySQLの“country”テーブルに“name_en”カラムがあり、これをハッシュのキーにして、 下記構文で“name_jp”カラムに文字列を挿入しようとしたのですが、 ----------------------------------------- $sth = $dbh -> prepare ("update country set name_jp = \'$name{name_en}\' where id between 1379 and 1396"); ----------------------------------------- 結果は何も入りませんでした。 カラム名をハッシュのキーにするには、どう書けばいいのでしょうか? 宜しくお願いします。

  • Perl
  • 回答数9
  • ありがとう数8

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

そこの文字列は「Perl の文字列」として解釈されるんだから, カラム名として使いたい文字列をハッシュのキーに使っても無意味じゃん. ちゃんと「name_en が 'USA' で name_jp が 'アメリカ合衆国' というタプル」を作らないと.

gellan
質問者

お礼

補足説明ありがとうございます。 つまりは、裏技であれ、反則技であれ、 ハッシュのキーをカラム名として認識させる記述方法は存在しないということですね。 タプルが分からなかったので調べてみたら、 Pythonという言語はたくさんヒットしましたが、 Perlに関する説明は見つかりませんでした。 %nameに入っている要素と同じ数だけcase whenで書き並べれば、 とりあえずは出来なくはないのですが、世界には国が195ヶ国あるらしいので。

その他の回答 (8)

回答No.9

文字のエンコードが中途半端だったので手なおししました。 文字のエンコードは以下が参考になると思います。 http://d.hatena.ne.jp/tokuhirom/20080408/1207619640 http://blog.livedoor.jp/dankogai/archives/51031595.html # sqlite_unicode => 1で自動でフラグ付きUTF8に変換するようにした。 # 空白2文字を全角空白にしていることに注意 use strict; use warnings; use utf8; use feature 'say'; use DBI; binmode STDOUT, ':encoding(utf8)'; my $db_name  = 'sqlite_test.db'; my $table   = 'user_info'; my %jp_name_of = (   JPN => '日本',   USA => 'アメリカ合衆国',   SPN => 'スペイン' ); my $dbh = create_test_db($db_name); create_test_table( $dbh, $table ); say '-- before'; dump_table( $dbh, $table ); my $update_sql = 'UPDATE ' . $table . ' SET name_jp = ? where id = ?;'; my $update_sth = $dbh->prepare($update_sql); my $fetch_sql   = "SELECT id, name_en FROM $table where id between 1379 and 1396;"; my $fetch_sth = $dbh->prepare($fetch_sql); $fetch_sth->execute; while ( my $ref = $fetch_sth->fetch() ) {   my $id   = $ref->[0];   my $name_en = $ref->[1];   $update_sth->bind_param( 1, $jp_name_of{$name_en} );   $update_sth->bind_param( 2, $id );   $update_sth->execute;   $dbh->commit; } say '-- after'; dump_table( $dbh, $table ); $dbh->disconnect; unlink $db_name; sub create_test_db {   my $db_name = shift;   if ( -f $db_name ) {     unlink $db_name;   }   my $dbh = DBI->connect(     'dbi:SQLite:dbname=' . $db_name,     '', '',     {       AutoCommit   => 0,       RaiseError   => 1,       sqlite_unicode => 1,     }   ) || die "$db_name : $!";   return $dbh; } sub create_test_table {   my $dbh  = shift;   my $talbe = shift;   my $sql     = 'CREATE TABLE '     . $table     . '(id integer primary key, name_en, name_jp)';   $dbh->do($sql);   $dbh->commit;   my $sth = $dbh->prepare(     'INSERT INTO ' . $table . '(id, name_en, name_jp) VALUES (?, ?, ?)' );   while ( my $line = <DATA> ) {     $line =~ s/\x0D?\x0A?$//;     my ( $id, $name_en, $name_jp ) = ( '', '', '' );     if ( $line =~ m/^(\S+)\s+(\S+)$/ ) {       $id   = $1;       $name_en = $2;     }     elsif ( $line =~ m/^(\S+)\s+(\S+)\s+(\S+)$/ ) {       $id   = $1;       $name_en = $2;       $name_jp = $3;     }     else {       die 'Unknown format : ', $line;     }     $sth->bind_param( 1, $id );     $sth->bind_param( 2, $name_en );     $sth->bind_param( 3, $name_jp );     $sth->execute;     $dbh->commit;   } } sub dump_table {   my $dbh  = shift;   my $talbe = shift;   my $sql = "SELECT * FROM $table;";   my $sth = $dbh->prepare($sql);   $sth->execute;   while ( my $ref = $sth->fetch() ) {     say "@$ref";   } } __END__ 1377   RUS     ロシア 1378   GER     ドイツ 1379   USA 1380   SPN 1381   JPN 1395   USA 1396   JPN 1397   USA     アメリカ合衆国 1398   ITL      イタリア

gellan
質問者

お礼

エンコードのために、わざわざ手直しをして頂き、ありがとうございました。 さて、自分にはちょっと理解の難しい記述内容なのですが、せっかく頂いたので、実行させない手はないと思い、注釈にある全角スペース部分を処理していると・・・??? この内容はMySQLで使えるのでしょうか? -------------------------------------------------------------------- my $dbh = DBI -> connect('dbi:SQLite:dbname= ・・・ -------------------------------------------------------------------- 接続の部分がこうなっていますが、もしやSQLite用? もう一ヶ所気になった点が、create_test_table サブルーチン内の -------------------------------------------- while ( my $line = <DATA> ) { -------------------------------------------- ですが、<DATA>の元データは一体どこにあるんでしょうか? 私の方も、前回示した内容に関して、デコード部の記述ミスを修正し、エンコード処理を加え、さらにUPDATEパターンを二種類作ってみました。ちょっとエラーが出たりで、試行錯誤はありましたが、最終的には下記内容で、どちらのパターンも上手く機能しました。 あっ、それからデコードなんですが、selectでSQLから読み込んだ id や name_en を、処理のどこかでデコードすると、最後に挿入されるエンコード済みの日本語国名($jp_name)がなぜか文字化けしてます。半角英数はむしろデコードしない方がいいのかな・・・??? 前回こちらの評価はして頂けなかったので、一応ご報告だけしておきます。ただ、もし、どこどこに問題点があるから、この内容は使わない方がいい、ということでしたら、その旨ご指摘下さい。 use strict; use warnings; use utf8; use Encode; use DBI; #---CSVファイルから国名データ読み込み my %jp_name_of = (); open (IN, './country_name.csv') or die "$!"; while (my $line = <IN>){ chomp $line; my ($name_e, $name_j) = split /\,/, (decode 'cp932', $line); $jp_name_of{$name_e} = $name_j; } close (IN); #---MySQL内の該当データをUPDATE my $dbh = DBI -> connect ('DBI:mysql:logs:localhost', [ユーザID], [パスワード]); my $select_sth = $dbh -> prepare ("select id, name_en from country where id between 1379 and 1396"); $select_sth -> execute(); ###---パターン1ここから--->>> while (my $ary_ref = $select_sth -> fetchrow_arrayref){ my ($id, $name_en) = @$ary_ref; my $jp_name = encode 'utf-8', $jp_name_of{$name_en}; my $update_sth = $dbh -> prepare ("update country set name_jp = \'$jp_name\' where id = \'$id\'"); $update_sth -> execute(); $update_sth -> finish(); } $select_sth -> finish(); ###---パターン1ここまで---/// =pipe ###---パターン2ここから--->>> my @array = (); while (my $ary_ref = $select_sth -> fetchrow_arrayref){ my ($id, $name_en) = @$ary_ref; push @array, [$name_en, $id]; } $select_sth -> finish(); foreach my $ref (@array){ my $id = $jp_name_of{$$ref[1]}; my $jp_name = encode 'utf-8', $jp_name_of{$$ref[0]}; my $update_sth = $dbh -> prepare ("update country set name_jp = \'$jp_name\' where id = \'$id\'"); $update_sth -> execute(); $update_sth -> finish(); } ###---パターン2ここまで---/// =cut $dbh -> disconnect(); exit();

回答No.8

- %nameだとわかりづらいので、%jp_name_ofにした。 - 表示がくずれるので、空白2文字を全角空白にしているていることに注意。 use strict; use warnings; use utf8; use feature 'say'; use DBI; use Encode; binmode STDOUT, ':encoding(utf8)'; my $db_name  = 'sqlite_test.db'; my $table   = 'user_info'; my %jp_name_of = (   JPN => '日本',   USA => 'アメリカ合衆国',   SPN => 'スペイン' ); my $dbh = create_test_db($db_name); create_test_table( $dbh, $table ); say '-- before'; dump_table( $dbh, $table ); my $update_sql = 'UPDATE ' . $table . ' SET name_jp = ? where id = ?;'; my $update_sth = $dbh->prepare($update_sql); my $fetch_sql   = "SELECT id, name_en FROM $table where id between 1379 and 1396;"; my $fetch_sth = $dbh->prepare($fetch_sql); $fetch_sth->execute; while ( my $ref = $fetch_sth->fetch() ) {   my $id   = $ref->[0];   my $name_en = $ref->[1];   $update_sth->bind_param( 1, $jp_name_of{$name_en} );   $update_sth->bind_param( 2, $id );   $update_sth->execute;   $dbh->commit; } say '-- after'; dump_table( $dbh, $table ); $dbh->disconnect; unlink $db_name; sub create_test_db {   my $db_name = shift;   if ( -f $db_name ) {     unlink $db_name;   }   my $dbh = DBI->connect(     'dbi:SQLite:dbname=' . $db_name,     '', '',     {       AutoCommit => 0,       RaiseError => 1     }   ) || die "$db_name : $!";   return $dbh; } sub create_test_table {   my $dbh  = shift;   my $talbe = shift;   my $sql     = 'CREATE TABLE '     . $table     . '(id integer primary key, name_en, name_jp)';   $dbh->do($sql);   $dbh->commit;   my $sth = $dbh->prepare(     'INSERT INTO ' . $table . '(id, name_en, name_jp) VALUES (?, ?, ?)' );   while ( my $line = <DATA> ) {     $line =~ s/\x0D?\x0A?$//;     my ( $id, $name_en, $name_jp ) = ( '', '', '' );     if ( $line =~ m/^(\S+)\s+(\S+)$/ ) {       $id   = $1;       $name_en = $2;     }     elsif ( $line =~ m/^(\S+)\s+(\S+)\s+(\S+)$/ ) {       $id   = $1;       $name_en = $2;       $name_jp = encode( 'utf8', $3 );     }     else {       die 'Unknown format : ', $line;     }     $sth->bind_param( 1, $id );     $sth->bind_param( 2, $name_en );     $sth->bind_param( 3, $name_jp );     $sth->execute;     $dbh->commit;   } } sub dump_table {   my $dbh  = shift;   my $talbe = shift;   my $sql = "SELECT * FROM $table;";   my $sth = $dbh->prepare($sql);   $sth->execute;   while ( my $ref = $sth->fetch() ) {     say decode( 'utf8', "@$ref" );   } } __DATA__ 1377   RUS     ロシア 1378   GER     ドイツ 1379   USA 1380   SPN 1381   JPN 1395   USA 1396   JPN 1397   USA     アメリカ合衆国 1398   ITL      イタリア $ perl -w data.pl -- before 1377 RUS ロシア 1378 GER ドイツ 1379 USA 1380 SPN 1381 JPN 1395 USA 1396 JPN 1397 USA アメリカ合衆国 1398 ITL イタリア -- after 1377 RUS ロシア 1378 GER ドイツ 1379 USA アメリカ合衆国 1380 SPN スペイン 1381 JPN 日本 1395 USA アメリカ合衆国 1396 JPN 日本 1397 USA アメリカ合衆国 1398 ITL イタリア

gellan
質問者

お礼

ループ処理の一例、ありがとうございます。 内容を一生懸命、いや、必死に読んでおりました。 見たこともないような記述がずらずらと(^^; 空白に関する注釈があったので、実行はしていませんが。 今も何をしているのか分からない部分が多々あります。 ただ、UPDATE以外のプロセスも含まれているようなので、UPDATEの部分はこういうことなのかなと、きちんと理解するためにも、その流れを私の書ける方法で書き出してみました。 #---CSVファイルから国名データ読み込み my %jp_name_of; open (IN, './country_name.csv') or die "$!"; while (my $line = <IN>){ chomp $line; my ($name_e, $name_j) = decode 'cp932', (split /\,/, $line); $jp_name_of{$name_e} = $name_j; } close (IN); 頂いたプロセスの中に上記は含まれていませんが、このプロセスがないと、次のUPDATEができないので。 #---SQL内の該当データをUPDATE my $select_sth = $dbh -> prepare ("select id, name_en from country where id between 1379 and 1396"); $select_sth -> execute(); while (my $ary_ref = $select_sth -> fetchrow_arrayref()){ my ($id, $name_en) = @$ary_ref; my $update_sth = $dbh -> prepare ("update country set name_jp = \'$jp_name_of{$name_en}\' where id = \'$id\'"); $update_sth -> execute(); $update_sth -> finish(); } $select_sth -> finish(); SELECTで該当レコードを引っ張って来て、1レコードずつ読み込んではUPDATEしていく。 \'$jp_name_of{$name_en}\'なら$name_enはハッシュのキーとして認識されたと思います。 理解としては、これでいいのでしょうか? あっ、それから余談になりますが・・・ use utf8; use Encode; の環境で、テキストからの読み込み/テキストへの書き出し時は、その都度decode/encodeしていますが、SQLの場合、select/insert、update時に、decode/encodeはしなくていいんだろうかと。 ネット上でdecode/encodeしている例を見たことがないので、私もしていないのですが、これはいつも気になってます。

回答No.7

ループではなくて、UPDATE一発でできないかということでしょうかね。 もしDB上にテーブルを作っていいなら、 dummy_table: name_en name_jp ---------- JPN 日本 SPN スペイン USA アメリカ合衆国 ... UPDATE target_table A   set A.name_jp = (select B.name_jp from dummy_table B                    where A.name_en = B.name_en)   where id between 1379 and 1396; でいけるかなぁ? UPDATE target_table 一時名 って書き方ができないDBもあったと思うけど

gellan
質問者

お礼

ご回答ありがとうございます。 ちゃんと理解して頂けたようで良かったです。 この処理は一時的にであれ、変換参照用テーブルを作る必要があるようですね。 特に作ってはいけない理由はないので、頂いた構文を実行するために作ってみました。 そして実行したら、ちゃんとname_jpにそれぞれの日本語国名が挿入されました。 ありがとうございました。 ループの件は、その前のお礼の中で、私が case when での処理に言及したからでしょう。 もしこの処理に case when を使うなら、条件部分を約150ヶ国分書き連ねなければなりません。 恐らく「その部分をループ処理で」とおっしゃったのだと思います。 そして、もしループ処理できるなら、条件部分に今度は%nameが使えそうな気がするので、 この case when のループ構文、一体どうやって書くのか非常に知りたかったのですが・・・ 当初の質問自体には既に「出来ない」という結論が出てしまっているので、 そろそろこの質問を締め切ろうと思うのですが、 上記 case when のループ構文だけが心残りで。 というわけで、あと2、3日待ってみます(^^;;;

回答No.6

質問の内容が理解できません。 1. %nameには何が入っているのか? 2. どういう文字列を期待しているのか? print "update country set name_jp = \'$name{name_en}\' where id between 1379 and 1396", "\n"; -> update country set name_jp = "USA" where id between 1379 and 1396 ??

gellan
質問者

補足

確かにただでさえ分かりづらい内容が、更に分かりづらくなってるかもしれません。 出来るだけ分かりやすく説明してみようと思います。 1) %name = ('USA' => 'アメリカ合衆国', 'SPN' => 'スペイン', 'JPN' => '日本', ・・・・); 上記のように、%nameには国名の要素が('英語3文字略称' => '日本語')の形式で150ヶ国分くらい格納されています。 データ自体はCSVファイルとしてあり、そこから読み込んだものです。 2) countryテーブルにはid, name_en, name_jpというカラムがあり(他のカラムもありますが)、idはintのauto_increment、name_enには国名の英語3文字略称が、name_jpにはname_enに対応する日本語国名が、それぞれ自動で追加されていくようになっています。 id    name_en   name_jp -------------------------------------- 1377   RUS     ロシア 1378   GER     ドイツ 1379   USA 1380   SPN 1381   JPN (中略) 1395   USA 1396   JPN 1397   USA     アメリカ合衆国 1398   ITL      イタリア ある日、このテーブルをチェックしてみると、上記のようにidが1379から1396まで、name_enにはデータが入っているものの、name_jpには何も入っていないことが判明しました(原因は不明です) そこで、この空欄部分を埋めるべく思い付いた方法がハッシュ%nameでした。 CSVファイルから国名データを読み込んで%nameに格納し、 --------------------------------------- "update country set name_jp = \'$name{name_en}\' where id between 1379 and 1396" --------------------------------------- を実行すれば、下のように各name_enの値がハッシュのキーとして代入され、 id    name_en              name_jp -------------------------------------------------------- 1379   USA   $name{'USA'} →  アメリカ合衆国 1380   SPN   $name{'SPN'} →  スペイン 1381   JPN   $name{'JPN'} →  日本 (中略) 1395   USA   $name{'USA'} →  アメリカ合衆国 1396   JPN   $name{'JPN'} →  日本 対応する日本語国名がname_jpに挿入されるだろうと考えたわけです。 しかし、実際にこれを実行してみると、\'$name{name_en}\'のname_en部分はカラム名ではなく、単なる'name_en'という文字列と認識されるようで、結果としてどのレコードもname_jpには何も挿入されませんでした。 ここで、この方法は無理なんだ、と諦めればよかったのでしょうが、もしかしたら自分が知らないだけで、裏技、神技、反則技のどれかを使えば、name_enをカラム名と認識させる記述方法が実はあるのかもしれない、と変なこだわりが出て、最終的にこうして質問を出してみたわけです。 というわけで、最終目標は、\'$name{name_en}\'のname_enを文字列ではなく、カラム名と認識させるSQL構文の記述方法だったのですが、No.3~No.4でTacosan氏に、そんな記述方法はない、という結論を頂いてしまいました。 すでに結論が出てしまっているので、本来なら質問を締め切るのが筋なのでしょうが、No.4でTacosan氏が書き残された最後の2行が気になったので、締め切らずに現在に至っているというわけです。 どうでしょうか? これで理解して頂けたでしょうか? もしまだご質問等ありましたら、遠慮なく言ってください。 そして、もし万一、裏技、神技、反則技のどれかをご存知なら、ぜひとも教えてください。

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.5

name_en     name_jp = $name{name_en} --------------------------------------- USA        アメリカ合衆国 SPN        スペイン JPN        日本 これを格納したテーブルはあるのですよね? ならば、Perl上ではハッシュを用いたデータを「別に」用意しなければならないです。 SELECTをexecuteして、 while (my $ary_ref = $sth->fetchrow_arrayref) { my ($name_en, sname_jp) = @$ary_ref; $name{$name_en}=$name_jp; } これでname_enをキーにname_jpを値に取ることのできるハッシュ変数%nameが作れると思います。

gellan
質問者

補足

ご回答頂き、ありがとうございます。 先ずテーブルの件ですが、「国名一覧」のようなテーブルは、今のところ特に作ってはいません。 CSVファイルでなら一覧はありますが、195ヶ国すべてを網羅しているわけではありません(^^; さて、本題なのですが・・・ なぜそのハッシュ%nameで私のやりたかった事ができるのか、 ちょっと内容が掴めない状態で戸惑っています>< そのハッシュを使って「set name_jp = $name{name_en}」としても name_enは単なる文字列と認識され、name_jpに値は入らないと思うのですが。 もしかして、私は何かとんでもない勘違いをしているのでしょうか? それとも、何か他の内容を説明されているのでしょうか? 鈍いヤツで申し訳ありませんが、もう少し詳しくご説明お願い致します。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

あれ? 「タプル」自体は SQL 方面でも特に珍しい言葉じゃないと思ったんだけど.... いずれにしても ・SQLサーバに渡すコマンド (文字列) を作るまでは Perl の世界 ・SQLサーバがコマンドを受け取ってからは SQL の世界 という 2つの世界があることを確認しておいた方がいいんじゃないかな. 念の為ですが, この 2つの世界は魔法でも使わない限り交わることはありません. 国の数がどうであれ, データ構造さえ作ってしまえばループするだけのことでは? まあ, しばしば「データ構造を作る」ところが問題になったりするんだが.

gellan
質問者

お礼

タブルは多分私が知らないだけなのだと思います。 もしやテーブルの事かな?などと思ったりもしたのですが・・・ あっ、あまり書くと無知の上塗りになってしまいますね(^^; %nameの要素を元に変換参照用テーブルを作って、joinしてupdateすれば、 確かにこんな面倒なことを考えなくても解決はします。 ただ、もしハッシュのキーをカラム名として認識させる記述方法があるなら、 今回だけでなく、今後も何かの時に使えそうな気がしたので、 あえてその処理方法にこだわって質問させて頂きました。 SQL構文の一部もしくは全体をループさせるような処理は書いたことがないので、 後学のために、今回の処理で一例を挙げてもらえませんか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

ハッシュのキーは (およそ) \w+ にマッチすれば自動的に文字列とみなされます. だから $name{name_en} でも $name{"name_en"} でも同じことだし, あるいは %name = ('USA' => 'アメリカ合衆国') と %name = (USA => 'アメリカ合衆国') も同じ意味だったりする. とはいえ, そもそもハッシュ %name に name_en ってキーで値は入れてあるの?

gellan
質問者

補足

ご回答ありがとうございます。 SQLのカラム名に、果たしてどれだけ半角英数以外の文字が使われているのかは知りませんが、 半角英数やハイフン、アンダーバーを用いるのが一般的という認識で、 いつもそれらのみを使用して名前を付けています。 ですから、カラム名はすべて\w+にマッチする名前になっています。 name_enはテーブルのカラム名であって、%nameの要素ではないので、 name_enというキーも、それに対応する値も、%nameには入っていません。 %name = ('USA' => 'アメリカ合衆国', 'SPN' => 'スペイン', 'JPN' => '日本', ・・・・)となっています。 確認のために、もう一度やりたいことを説明しますと・・・ 例えば、"hinichi"というカラムに日付(4桁年-2桁月-2桁日)が入っていれば、 year関数を使ってyear(hinichi)とすると、その日付の年が取得できます。 hinichi        year(hinichi) -------------------------------------- 2013-09-10     2013 2012-10-05     2012 2010-03-06     2010 これと同じように、%nameを関数のように考えて、 name_en     name_jp = $name{name_en} --------------------------------------- USA        アメリカ合衆国 SPN        スペイン JPN        日本 という構想で、name_jpに日本語の国名を挿入したかったのです。 ですから、name_enはカラム名として認識される必要があり、 単なる文字列と認識されては困るというわけです。 name_enをカラム名として認識させる記述方法はないでしょうか?

  • hirotn
  • ベストアンサー率59% (147/246)
回答No.1

例えば以下でしょうか…。 ("update country set name_jp = \'" . $name{"name_en"} . "\' where id between 1379 and 1396"); . は文字列結合演算子です。あるいは、 ("update country set name_jp = \'$name{'name_en'}\' where id between 1379 and 1396");

gellan
質問者

補足

素早いご回答にびっくりしました。 どうもありがとうございます。 さて早速、頂いた構文を両方とも試してみました。 しかし残念ながら、どちらの構文でもname_jpカラムには何も挿入されませんでした。 %nameには('USA' => 'アメリカ合衆国')も格納されているので、 試しに下記二つを実行してみたら、 ------------------- ("update country set name_jp = \'".$name{"USA"}."\' where id between 1379 and 1396"); ------------------- ("update country set name_jp = \'$name{'USA'}\' where id between 1379 and 1396"); ------------------- どちらの場合も、nama_jpカラムに'アメリカ合衆国'と挿入されました。 どちらの構文でも、ハッシュのキーは、カラム名ではなく、単なる文字列として認識されているようです。

関連するQ&A

  • ハッシュのキー追加について

    とある既存プログラムに機能追加したいのですが上手くいきません。 ハッシュだとは思うのですが、%だったり$だったりしてよくわからなくなってしまいました。 どこがおかしいか教えていただけないでしょうか。 <概要> もともとあった(1)と(3)の処理の間に、(2)を行う <ソース> (1)DBから1レコードを取得する $sql = "select * from tenpo where id=5;"; $sth = $dbh->prepare($sql); $sth->execute(); $shop = $sth->fetchrow_hashref(); (2)別TABLEから値を取得し、(1)に追加する $sql = "select todoufuken from area where id=5;"; $sth = $dbh->prepare($sql); $sth->execute(); @todoufuken= $sth->fetchrow_array; $shop{place} = $todoufuken[0]; (3)$shopの情報をサブルーチンに渡す ソース略

    • ベストアンサー
    • Perl
  • Mysqlの接続について

    現在、以下のようなperlのスクリプトを作っているのですが、mysqlへの接続,切断は以下の場合、どちらにした方がいいのでしょうか? (1)の場合 use DBI; $dsn="DBI:mysql:database=dbname:host=localhost"; $dbh=DBI->connect($dsn,'user','pass'); $sth = $dbh->prepare("SELECT no,title,name,date,host From `table1` where no='1'"); $sth->execute; $sth->fetchrow_array; $sth->finish; $sth2 = $dbh->prepare("SELECT no,title,name,date,host From `table2` where no='1'"); $sth2->execute; $sth2->fetchrow_array; $sth2->finish; $dbh->disconnect; (2)の場合 use DBI; $dsn="DBI:mysql:database=dbname:host=localhost"; $dbh=DBI->connect($dsn,'user','pass'); $sth = $dbh->prepare("SELECT no,title,name,date,host From `table1` where no='1'"); $sth->execute; $sth->fetchrow_array; $sth->finish; $dbh->disconnect; $dsn="DBI:mysql:database=dbname:host=localhost"; $dbh=DBI->connect($dsn,'user','pass'); $sth2 = $dbh->prepare("SELECT no,title,name,date,host From `table2` where no='1'"); $sth2->execute; $sth2->fetchrow_array; $sth2->finish; $dbh->disconnect; (1)の場合と(2)の場合の違いは、(1)の場合、最初にデータベースに接続して、一番最後に切断する事で、(2)の場合、毎回データベースへの接続と切断を行う事が違います。 (2)の場合、毎回接続と切断を行うので、2回ほどではあまり変わらないかもしれないのですが、もし10回とか接続と切断を行うとかなり負荷が高くなるような気がするのですが、他のHPなどを拝見すると接続をしたら切断を行うように癖をつけるようにした方がいいと書かれていたりします。 どちらの方が正しいやり方というか、負荷がすくなく使えるのでしょうか?

    • ベストアンサー
    • Perl
  • MySQLとの接続でfetchrow_arrayがwhile文で使えない

    こんばんは、皆さん。 MySQLをPerlから使いたいのですが、 以下のようにやっても、$flagに"OK"が入りませんでした。 つまり、whileは一度もループしないで抜けてしまっているようです。 ------------------------------------------------- use DBI; … sub dbtest{ $dbh = DBI->connect("dbi:mysql:hogeDB:localhost","user","pass"); $sql = "select hoge,fuge from t_name where key='value'"; $sth = $dbh->prepare($sql); $sth->execute; while( ($hoge, $fuge) = $sth->fetchrow_array ){     $flag = "OK"; } $sth->finish; $dbh->disconnect; } ------------------------------------------------- ※実際はユーザ名などは変数にしています。 バージョンは現在、 Perl:v5.8.5 MySQL:5.1.6-alpha となっているようです。 それとちょっと別件ですが、 use autouseの書式は以下でよいのでしょうか? 「use autouse DBI;」 しかし、これだけだとDBIが読み込めてないエラーになるようです。 ご教示よろしくお願いします。

    • ベストアンサー
    • Perl
  • MySQLのトランザクションについて

    初めて質問します。 今、PerlのDBIを使ってMySQLのトランザクション処理にチャレンジしています。 ところが、rollback処理がうまくできません。 具体的には、 table2 がある状態で下のプログラムを動かすと、 エラーの表示が出るのに、 table1 は作成されました。 何らかのエラーがあれば、どちらも作成されないようにしたいです。 ======================================================= my %sql; $sql{db_name} = "database"; $sql{host} = "localhost"; $sql{user_name} = "user_name"; $sql{password} = "password"; use DBI; my $dbh = DBI->connect('DBI:mysql:'.$sql{db_name}.':'.$sql{host}, $sql{user_name}, $sql{password} ,{RaiseError => 1, PrintError => 0, AutoCommit => 0 }) || &Err(); my $sth; my $re; eval { my $sql_string1 = "create table table1(`id` int);"; my $sql_string2 = "create table table2(`id` int);"; $sth = $dbh->prepare($sql_string1); $re = $sth->execute; $sth = $dbh->prepare($sql_string2); $re = $sth->execute; }; if ($@) { $tag="Err:".$@."\n"; $sth = $dbh->rollback; }else{ $sth = $dbh->commit; } $sth->finish; $dbh->disconnect; ======================================================= 検索して、いろいろいじっても解決しませんでした。 どうかよろしくお願いします。

    • ベストアンサー
    • Perl
  • perl+mysqlで変数が使えなくて困ってます。

    use DBI; $id=1; $nm="gootarou"; $mm="friend"; $user = '***'; $passwd = '***'; $db = 'DBI:mysql:***'; $dbh = DBI->connect($db, $user, $passwd); $sth = $dbh->prepare("INSERT INTO list (id,name,memo) VALUES ($id,$nm,$mm)"); $sth -> execute; $sth -> finish; $dbh -> disconnect; exit; mysqlの勉強を始めたところでいきなり壁にぶちあたってしまいました^^; googleその他で検索かけてみましたが解決に至りませんでしたので 質問させてください。 >$sth = $dbh->prepare("INSERT INTO list (id,name,memo) VALUES ($id,$nm,$mm)"); ↑ここの部分を >$sth = $dbh->prepare("INSERT INTO list (id,name,memo) VALUES ('1','gootarou','friend')"); と直接入力してやれば問題なく登録されるのですが、変数を使うと正常に処理がされません。 数字を変数に代入したものは大丈夫なのですが 英字や二バイト文字を変数に代入したものが問題あるようです。 それぞれのフォームの型はvarchar(100)で設定しています。 ループで一括処理したいのですが変数が使えないことには・・と困ってます。 よろしくお願いします。

  • SQLで別テーブルの参照

    こんにちは。 PostgreSQL+Perl+DBIでCGIを書いています。 テーブルからデータを取得する場合なのですが、table1にはIDのみが登録されていて、table2には、そのIDに対する文字列が登録されているとします。 このような場合に、tableからIDを取得して、そのIDに対するtable2の文字列を一気に取得することは可能でしょうか? つまり、 $dbh=DBI->connect(~); $sth=$dbi->prerare("SELECT id FROM table1 WHERE ~;"); $sth->excecute(); $id=$sth->fetchrow; $sth->finish(); $sth=$dbi->prerare("SELECT str FROM table2 WHERE id=$id;"); $sth->excecute(); $str=$sth->fetchrow; $sth->finish(); $dbh->disconnect(); といった処理をこんな感じに一度に行いたいのです。 $dbh=DBI->connect(~); $sth=$dbi->prerare("~~~~~;"); $sth->excecute(); $str=$sth->fetchrow; $sth->finish(); $dbh->disconnect(); 可能かどうかもわからないのですが、なにか良い方法はありますでしょうか?よろしくお願いします。

  • mysql 最大値 取得 

    mysqlのデータベースから、列の最大値を取り出したいのですが、 以下のように書いているのですが、取得される値が1しか返ってこないです。 間違っているところはあるでしょうか? perlで書いています。 my $dbh = DBI->connect("DBI:mysql:host=${db_host};database=${db_name}", $db_user, $db_pass); my $sth = $dbh->prepare("SELECT MAX(列名) FROM テーブル名"); my $rv = $sth->execute(); print "$rv";

    • ベストアンサー
    • MySQL
  • 一回の処理で、2回以上データベースに対してアクセスできない??(perlDBIを使用)

    質問があるのですが、よろしくお願いします。 use DBI; $dbuser = 'root'; $passwd = 'abc'; $db = DBI->connect('DBI:mysql:DB:localhost',$dbuser, $passwd); $prepare = "select MAIL from user where USER_ID = $userid"; $sth->prepare("$prepare"); $sth->execute; @user = $sth->fetchrow_array; $sth->finish; while( ($key, $value) = each %in ){ $sth = $db->prepare("UPDATE user SET $key = '$value' where USER_ID = $in{userid}"); $sth->execute; $sth->finish; } $db->disconnect; という処理を行わせたいのですが、どうもUPDATE文の辺りで、処理が止まってしまっているようなのです。select文はしっかり実行されている形跡があるのですが、1回の処理で2回以上データベースに対してアクセスすることは出来ないのでしょうか? どなたか分かる方いらっしゃいましたらご教授のほどよろしくお願いします。

    • ベストアンサー
    • MySQL
  • すでに接続してあるデータベースについて

    mysqlデータベースにperlで接続する際は、 use DBI; $dsn="DBI:mysql:database=test:host=localhost"; $dbh = DBI->connect($dsn,user,passwd); とし、データベースに接続して、 $sth = DBI->prepare("SELECT * From `table`); ・・・・・・ と続いていくと思いますが、 すでにデータベースに接続(コネクション)していた場合、どのように書けばいいのでしょうか? どなたかよろしくお願いします。

    • ベストアンサー
    • Perl
  • SQLが応答しなくなっているのか、CGIが読み込み中のままになってしまいます。

    SQLを約1600回実行したら、5秒後にページを再読み込みします。 print "<html><body onload=\"setTimeout('location.reload()',5000)\">"; foreach ... {   ...   # 約1600回繰り返す   @result = select("SQL文");   ... } sub select{   my @result = ();   my($dbh, $sth);   $dbh = DBI->connect('DBI:mysql:データベース:localhost', "ID", "パスワード") or return 0;   $sth = $dbh->prepare("$_[0]");   $sth -> execute() or return 0;   $num_rows = $sth->rows;   $num_of_fields = $sth->{NUM_OF_FIELDS};   $result[0] = $sth->rows;   for ($i=1; $i<=$num_rows; $i++) {     @fetchrow_array = $sth->fetchrow_array;     $result[$i] = join ',', @fetchrow_array   }   $sth -> finish();   $dbh -> disconnect();   return @result; } 最初の1,2回は期待通りに動くのですが、 2,3回ほど再読み込みをすると、「読み込み中」のままになってしまいます。 (期待通りに動く場合、1回の読み込みは20秒程度です。) タスクマネージャを見ると、 期待通りに動いているときは、CPU使用率が60%くらいになっていますが、 「読み込み中」のままの時は1%程度になっています。 SQLサーバーから応答がなくなっているのでしょうか? (簡単なSQLにしてみても同じでした。) 原因がわかる方、よろしくお願いします。 WindowsXP SP2 Apache1.3 ActivePerl5.6 MySQL3.23

    • ベストアンサー
    • CGI

専門家に質問してみよう