
以前似たような質問をしたモノですが、
Perl(cgi)ファイルからテーブル内の一定の項目をDELETEしようとしています
具体的にいうと、多数あるチェックボックスにチェックされた項目のみを削除するプログラムで、チェックされた値はハッシュに格納し読み込み、削除をしています。
foreach $key (keys %hash)
{
# 取り出した値を$noに代入
$no = $hash{$key};
# SQL発行
$sql = $db->prepare("DELETE FROM テーブル名 WHERE レコード指定名='$no'");
# SQL実行
$sql->execute;
}
もしくは
# ハッシュに入れた値をカウント
$n = keys( %hash );
# プレースホルダを使用し削除の実行
$sql = $db->prepare("DELETE FROM テーブル名 WHERE レコード指定名=?");
for($i=0; $i<$n; $i++)
{
# SQL実行
$sql->execute(@hash{$i});
}
上記の方法でどちらも問題なく実行できているのですが、ご覧のようにハッシュに格納されている数だけ$sql->execute;を実行しているため効率が悪い、と担当者から指摘をうけました。
少しでもマシンの負担を軽くし、スムーズにするためにexecuteをまとめて実行することを求められています。
selectcol_arrayref などを使う方法などを検索できたのですが、具体的なサンプルがないとまだ分からない初心者で、上記のプログラムに当てはめる方法が分からないでいます。
ご教授のほどよろしくお願いします。

No.2ベストアンサー
- 回答日時:
perlのmysql 用モジュールの方は使ったことはないけど、phpと同様だろうと考えて回答してみます。
せっかくプレースホルダーを使ったsql文が使えているのだから、プレースホルダーに入れるようにすれば、データが数値か文字列かのチェックやエスケープ対策も出来るはずです。
# ハッシュに入れた値をカウント
$n = keys( %hash );
# プレースホルダーを使用し削除用 sql文 作成
$sql = $db->prepare("DELETE FROM テーブル名 WHERE カラム名 in (". join(',', map{'?'}[1..$n]) . ")");
### データバインド用の関数があるはずなので、データ配列と、データ型指定用配列または文字列をセットする。
### 関数名、引数の与えかたは使ってるモジュールのドキュメントを調べて下さい。
$sql->?bind?( データ、カラム型指定 );
# sql 実行
$sql->execute();
hrm_mmm様、回答ありがとうございます。
かなり勉強になるソースありがとうございます。
map関数はもちろん、このようなプレースホルダーの効率の良い使用方法があるんですね。
参考にさせて頂きます。
ちなみに、今回のようなSQL文をいろいろ応用し作成するやり方を知るいいサイト、もしくは参考書はあるのでしょうか?
経験し積み重ねていくしかないのでしょうか?
もし、参考見聞があれば教えて下さい。
No.3
- 回答日時:
> ループで文字を連結させていく方法が思いつかなかったので、join関数を
> 使い強引に文字を連結させてみました。
> 今回は、値が全て数値だったのでこの方法でできましたが、値が文字列
> だった場合join関数では『”(ダブルコーテーション)』で区切るわけでは
> ないのでできなくなります。
joinする前にmap関数でシングルクォートでくくるというのはどうですか。
@a = ( 'a','b','c','d' );
$b = join( ",", map{ "'".$_."'"; } @a );
$sql = "select * from テーブル where カラム in ( $b )";
みたいに
nora1962様、回答ありがとうございます。
回答頂いたやり方で文字列も解決できそうです。
プログラムを勉強し始めて2ヶ月たつのですが、今回のような関数の見つけ方が未熟で皆さんにお手数かけています。
早く自分で解決できるように力を付けたいと思います。
ありがとうございました。
No.1
- 回答日時:
「=」条件でprepare&executeするのでなく、in条件を指定すればいいのでは?
ループ内ではSQL文の組み立て(in条件の値リストをどんどん文字連結していく)を行い、ループから抜けた後にprepareとexecuteするといった方法です。
「select ~ from ~ where 列名 in(値1,値2, ~ ,値n)」といったSQLを作ることになります。
この回答への補足
chukenkenkou様、ご返答ありがとうございます。とても助かりました。
下記のプログラムで一応動かすことができました。
@s_del = values(%hash); # ハッシュの値のみを全て配列に代入
@s_del = join( ',', @s_del); # 配列を連結
$sql = $db->prepare("DELETE FROM テーブル名 WHERE レコード名 IN (@s_del)");
$sql->execute;
ループで文字を連結させていく方法が思いつかなかったので、join関数を使い強引に文字を連結させてみました。
今回は、値が全て数値だったのでこの方法でできましたが、値が文字列だった場合join関数では『”(ダブルコーテーション)』で区切るわけではないのでできなくなります。
ループ内でSQL文の組み立て(in条件の値リストをどんどん文字連結していく)方法として何かいい方法はあるでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
mysqlがインストールされている...
-
mysqlのupdate構文についての質...
-
エラー 1068 (42000): 複数の主...
-
データベースの接続に失敗して...
-
#1062 - '0' は索引 'PRIMARY' ...
-
[XAMPP Control Panel v3.2.4] ...
-
同一日に複数レコードがある場...
-
MAMP 99ドル約1.6万円 高い...
-
あってますか?SQL
-
WHERE `年月日` = '晴' OR `年...
-
SQLです教えてくださいお願いし...
-
SQLを作ったのですがうまくいき...
-
(初心者)MySQLやmaraDBで、crea...
-
SQLです教えてくださいお願いし...
-
SQLです教えてくださいお願いし...
-
SQLです教えてください。
-
SQLです教えてくださいお願いし...
-
SQLです教えてくださいお願いし...
-
SQLです教えてくださいお願いし...
-
utf8bomとutf8mb4の違いがいま...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
コメントが消えてしまいます
-
.sqlのファイルをそのままコマ...
-
mysqlバッチモードでのエスケー...
-
ダブルコーテーションやシング...
-
SQLiteについて
-
mysqlがインストールされている...
-
MySQLカラム名は日本語と英数字...
-
ODP.NETのバージョン確認
-
副問合せにLIKE文を使う方法は...
-
SQLのVARCHARとVARCHAR2の違い
-
エクセルで連勤チェックをした...
-
ERROR 1045 (28000) (using pas...
-
旧filemakerで和暦(令和など)...
-
列数が多いと結果が行単位に改...
-
Usage: \\.<filename> | sourc...
-
VBAで変数内に保持された二次配...
-
INT型は金額の型に使用するべき...
-
like句を使って日本語を検索す...
-
mysqlへのインポート処理がうま...
-
テーブル作成でエラーが出てき...
おすすめ情報