--- title: プレースホルダを用いる author: kazu634 date: 2009-07-29 wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4729;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - Perl ---
PerlでDBを操作する際に、ユーザーからデータの入力を受け付けたい場面があります。例えば今回私が作成したウェブページでは住所を入力してもらい、それからクエリーを作成しています。こんな風に:
この際に、安易にコーディングしてしまうと、住所の入力を求めるテキストボックスエリアにSQL文を入力した場合に任意のSQL文が実行されてしまいます。それを防ぐためにプレースホルダという仕組みがあります。
このプレースホルダを使用すると、仮にSQL文が入力されても無害にしてくれる…そんな仕組みです。
次のようにして事前に用いるSQL文を試してみます。
kazu634@kazu634-desktop% mysql -uroot -pmusashi ~/public_html/cgi-bin [3508] Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 93 Server version: 5.0.75-0ubuntu10.2 (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use sample; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> SELECT address FROM renoir WHERE address LIKE '東京%'; +---------------------------------------------+ | address | +---------------------------------------------+ | 東京都豊島区東池袋1-40-2 | | 東京都豊島区東池袋1-42-8 | | 東京都豊島区巣鴨1-15-1 | | 東京都文京区本郷4-37-13 | | 東京都品川区大崎1-6-4 | | 東京都中野区中野5-61-2 | | 東京都中野区中野5-67-5 | | 東京都中央区銀座2-7-18 | | 東京都中央区銀座2-5-5 | | 東京都中央区銀座2-8-15 | | 東京都中央区銀座2-11-6 | | 東京都中央区銀座3-3-11 | | 東京都中央区銀座6-12-10 | | 東京都中央区銀座5-15-1 | | 東京都中央区日本橋2-3-6 | | 東京都中央区日本橋本町1-1 | | 東京都中央区八重洲1-6-17 | | 東京都中央区八重洲1-7-4 | | 東京都大田区大森北1-1-10 | | 東京都大田区西蒲田8-1-7 | | 東京都台東区上野6-1-1 | | 東京都台東区上野4-10-7 | | 東京都台東区上野2-13-13 | | 東京都台東区谷中7-20-6 | | 東京都千代田区五番町 | | 東京都千代田区富士見2-2-6 | | 東京都千代田区三崎町3-6-13 | | 東京都千代田区内神田2-9-9 | | 東京都千代田区内神田3-21-8 | | 東京都千代田区鍛冶町2-1-4 | | 東京都千代田区有楽町1-6-1 | | 東京都千代田区外神田1-16-10 | | 東京都千代田区外神田1-11-6 | | 東京都千代田区神田佐久間町1-18 | | 東京都杉並区阿佐ヶ谷南2-14-10 | | 東京都杉並区高円寺北2-4-4 | | 東京都新宿区西新宿1-24-1 | | 東京都新宿区西新宿1-17-1 | | 東京都新宿区西新宿1-5-11 | | 東京都新宿区西新宿7-23-2 | | 東京都新宿区新宿2-19-1 | | 東京都新宿区新宿3-4-1 | | 東京都新宿区市谷田町1-3 | | 東京都新宿区四谷1-3-22 | | 東京都新宿区歌舞伎町1-3-5 | | 東京都新宿区歌舞伎町1-14-4 | | 東京都新宿区歌舞伎町1-26-6 | | 東京都新宿区西新宿7-1-1 | | 東京都新宿区西新宿7-9-7 | | 東京都新宿区百人町1-18-8 | | 東京都新宿区百人町2-11-25 | | 東京都新宿区高田馬場2-18-6 | | 東京都新宿区高田馬場2-14-2 | | 東京都新宿区高田馬場1-34-8 | | 東京都新宿区高田馬場1-34-12 | | 東京都渋谷区代々木1-30-6 | | 東京都渋谷区千駄ヶ谷1-30-8 | | 東京都渋谷区桜丘町15-15 | | 東京都渋谷区渋谷2-17-5 | | 東京都渋谷区宇田川町36-2 | | 東京都渋谷区渋谷1-16-14 | | 東京都荒川区西日暮里5-23-6 | | 東京都荒川区東日暮里5-51-11 | | 東京都港区赤坂3-10-2 | | 東京都港区新橋4-10-2 | | 東京都港区新橋1-17-2 | | 東京都港区芝5-34-7 | | 東京都港区芝大門2-3-1 | | 東京都港区港南2-3-29 | | 東京都港区高輪3-25-22 | | 東京都江東区亀戸2-20-7 | | 東京都葛飾区東金町1-42 | | 東京都立川市柴崎町3-4-14 | | 東京都立川市曙町2-13-10 | | 東京都立川市曙町2-9-1 | | 東京都武蔵野市中町1-6-7 | +---------------------------------------------+ 76 rows in set (.00 sec) mysql> exit Bye
#!/usr/bin/env perl # === Libraries === use strict; use warnings; use Data::Dumper; use CGI; use CGI::Carp; use DBI; # === Main part === my $q = new CGI; my $query = $q->param('adr') || '東京'; # データベースへの接続 my $dbh = DBI->connect( 'dbi:mysql:dbname=sample', 'root', 'musashi', { RaiseError => 1, AutoCommit => } ); # ステートメントハンドラの作成 # ここでプレースホルダを指定している my $sth = $dbh->prepare("SELECT address FROM renoir WHERE address LIKE ?;"); # ステートメントハンドラの実行 # プレースホルダに入れ込む変数を指定している $sth->execute("$query%"); print("Content-type: text/html; char-set=utf-8\n\n"); print("<table width=\"\" cellspacing=\"\" cellpadding=\"\" border=\"\">\n"); print("<tr>\n<th>住所</th>\n</tr>\n"); while ( my @row = $sth->fetchrow_array ) { print "<tr>\n<td>@row</td>\n</tr>\n"; } print("</table>"); # ステートメントハンドラの解放 $sth->finish; # データベースハンドラの解放 $dbh->disconnect;
<html> <head> <title>DB test</title> <meta name="Content-Type" content="text/html; charset=UTF-8" /> <meta name="Content-Script-Type" content="text/javascript" /> </head> <body> <style type="text/css"> html, body { width: 100%; height: 100%; } html { overflow: hidden; } body { margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; } #mymap { margin-bottom: 80%; height: 25%; width 25%; } #bottompanel { position: absolute; left: 0px; border solid; bottom: 0px; height: 75%; width: 25%; overflow: auto; padding: 0px 5px 0px 10px; } </style> <script type="text/javascript" src="prototype.js"></script> <script type="text/javascript"> //<![CDATA[ function lwws() { // 結果の表示先に「しばらくお待ちください」と表示する document.getElementById("result").innerHTML = "<p>しばらくお待ちください...</p>"; new Ajax.Updater( "result", "cgi-bin/mysql.pl", { parameters : Form.serialize("ajax"), method : "post" } ); } //]]> </script> <div id="mymap"> <h1>DB test</h1> <form method="post" id="ajax" action="" name="ajax"> 住所: <input type="text" name="adr"> <input type="button" value="送信" onclick="lwws()"> </form> </div> <div id="bottompanel"> <div id="result"></div> </div> </body> </html>
prepareの部分で「?」を用いましょう!