Perlのプログラムでエラーが出ます。

普段PHPerなんですがbatchの関係でperlを使用しなければならなくなり書いていたんですが、
下記のソースコードの中でINSERT INTOの部分でエラーが発生してしまいます。

最初selectしている部分はcreate tableで作っているテーブル構成と同じです。

それからサイト名に関するレコード部分は*で隠しています。

よろしくお願いいたします。

回答の条件
  • 1人50回まで
  • 13歳以上
  • 登録:2013/12/22 00:44:15
  • 終了:2013/12/29 00:45:03
id:unnoub

ソースコードは以下のとうりです。
#!/usr/bin/perl
use DBI;
# データソース
$d = 'DBI:mysql:a_anime';
# ユーザ名
$u = '************';
# パスワード
$p = '************';

# データベースへ接続
$dbh = DBI->connect($d, $u, $p);

$sth = $dbh->prepare("select * from tweet where tweetid BETWEEN '1' AND '21562745' limit 5");
$sth->execute;
while( @row = $sth->fetchrow_array ){
$priduct_id = @row['3'];
$user_url= @row['6'];
$sth2= $dbh->prepare("show tables from a_anime like 'tweet_@row['3']'");
$sth2->execute;
@row2 = $sth2->rows;
$sth2->finish;
if (@row2 != 1){
$sth22= $dbh->prepare("CREATE TABLE `tweet_@row['3']` (
`id` int(255) NOT NULL auto_increment,
`userid` int(25) DEFAULT NULL,
`text` text NOT NULL,
`product_id` int(255) NOT NULL,
`product_name` varchar(30) NOT NULL,
`date` varchar(20) NOT NULL,
`user_url` varchar(160) NOT NULL,
`username` varchar(100) NOT NULL,
`flag` int(1) NOT NULL DEFAULT '1',
`rev_point` int(1) NOT NULL DEFAULT '1',
`t_tweetid` bigint(255) DEFAULT NULL,
`rev_id` int(10) DEFAULT NULL,
`rev_flag` int(1) NOT NULL DEFAULT '0',
`*****_flag` int(1) DEFAULT NULL,
`res_info` int(100) DEFAULT NULL,
`fav_info` int(255) DEFAULT NULL,
`user_img` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index3` (`flag`),
KEY `user url` (`user_url`),
KEY `t_tweetid` (`t_tweetid`),
KEY `index4` (`flag`,`rev_point`,`product_id`),
KEY `index5` (`flag`,`product_id`),
KEY `index6` (`userid`,`flag`),
KEY `index7` (`username`,`flag`),
FULLTEXT KEY `index2` (`text`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8");
$sth22->execute;
$sth22->finish;
}
$sth3= $dbh->prepare("select user_url from tweet_@row['3']");
$sth3->execute;
print "@row['3']\n";
print "@row['6']\n";
@row3 = $sth3->fetchrow_array;
$sth3->finish;
#if ($user_url != $row3){
print @row['2'] ;
print "\n";
$sth4 = $dbh->prepare("INSERT INTO tweet_@row['3'] VALUES (@row['1'],@row['2'],@row['3'],@row['4'],@row['5'],@row['6'],@row['7'],@row['8'],@row['9'],@row['10'],@row['11'],@row['12'],@row['13'],@row['14'],@row['15'],@row['16'])");
print $sth4;
print "\n";
$sth4->execute;
$sth4->finish;
}
}
$sth->finish;
$dbh->disconnect;

回答(1件)

id:TransFreeBSD No.1

TransFreeBSD回答回数662ベストアンサー獲得回数2642013/12/22 15:45:23

SQL文内にSQLとしてまずい文字が含まれているんじゃないでしょうか?
いちいちクォートするのも大変ですからプレースホルダをつかったら良いと思います。
http://ash.jp/db/dbi_dbd.htm 後半プレースホルダとバインドより

つまり、プレースホルダを使うことで、文字列のクォート等の手間を省くことができるわけです。

http://perldoc.jp/docs/modules/DBI-1.612/DBI.pod#Outline32Usage

  $sth = $dbh->prepare("INSERT INTO table(foo,bar,baz) VALUES (?,?,?)");

  while(<CSV>) {
    chomp;
    my ($foo,$bar,$baz) = split /,/;
        $sth->execute( $foo, $bar, $baz );
  }

あとperl的定型文法として~ or die ~を使い、エラーメッセージを補足しデバッグに役立てます。
http://perldoc.jp/docs/modules/DBI-1.612/DBI.pod#Placeholders32and32Bind32Values

  my $sth = $dbh->prepare(q{
    INSERT INTO sales (product_code, qty, price) VALUES (?, ?, ?)
  }) or die $dbh->errstr;
  while (<>) {
      chomp;
      my ($product_code, $qty, $price) = split /,/;
      $sth->execute($product_code, $qty, $price) or die $dbh->errstr;
  }
  $dbh->commit or die $dbh->errstr;

ちなみに「q{~}」は"'"をエスケープする必要のない「'~'」相当です。

あと、これはどうでもいいですけどprepare, execute, finishを連続してつかうならdoがおすすめです。
http://perldoc.jp/docs/modules/DBI-1.612/DBI.pod#do

例えば:

  my $rows_deleted = $dbh->do(q{
      DELETE FROM table
      WHERE status = ?
  }, undef, 'DONE') or die $dbh->errstr;

プレースホルダとバインド変数(@bind_values) を do メソッドで使うと、 $statement の中の変数を正しくクォートしなくてもよくなるためにとても 便利です。 しかしもし文を何度も実行するのであれば、代わりに 一度 prepare し、何度も execute するほうがより効率的です。

この例で使われている q{ ...} 形式のクォートは、文で 使われているかもしれないクォートの対応を壊されないように使われています。 文字列に入っている変数を解釈したい場合には、ダブルクォート風 qq{...} 演算子を使います。 詳細は "Quote and Quote-like Operators" in perlop をご覧ください。


それと配列の添字はクォートがいりません。
#あってもOKなのに驚いた

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません