(質問1)
数十秒から数分おきに50〜100件程度のデータを追加する際、通常はどのような流れで行うのでしょうか?
(追加しようとするデータには既に登録してあるデータも含みます)
例えば、1件ずつ登録済みかをチェックしながら未登録であれば追加登録する。
または、一気に全てを登録してから重複データを削除する。
など。。。
また、登録してあるデータの量にもよってその方法は変わるのでしょうか?
(質問2)
データを登録しようとする際「'」や「"」が含まれているとエラーになりますが、
「¥'」「¥"」とするとエラーは無くなります。
通常はそうするものなのでしょうか?
手順1)copyにてテキストファイルを丸ごと作業テーブルに読み込み
http://www.postgresql.jp/document/pg813doc/html/sql-copy.html
手順2)insertにて更新
http://www.postgresql.jp/document/pg721doc/reference/sql-insert....
カンマやクォートなどは区切り文字として使われるため、そこでデータが区切られてしまっておかしな事になってしまいエラーとなります。
そこで、カンマやクォートを本来の役割から外して(エスケープさせて)文字として認識させるために\を付けます。(\はエスケープ文字と呼ばれます)
(質問1)
1回の登録件数が1件なら前者で良さそうですが、
多数のデータを一括処理するなら、1件ずつチェックしながら登録だと効率があまり良くなさそうです。
後者のようなパターンの方が効率が良いのではないでしょうか。
(追加途中に閲覧されると複数見えてしまって格好悪いことになるので、実際には登録から削除までを一つのトランザクションとした方が良いかと思われます)
ただ、どちらでなければならないと言うほど明確な違いは無いと思います。
(重複確認に使用するフィールドにインデックスを作成してあれば)
(質問2)
’等は SQL で区切りに使われる文字なので、エスケープしないと使用できません。
また、このことをよく認識したうえでプログラムを組んでおかないと、SQL インジェクションの脆弱性となり、深刻な被害を生むことがありますので、ご注意ください。
詳しくはIPA ISEC セキュア・プログラミング講座のデータベース編や、[ThinkIT] 第1回:Webアプリケーション開発者が知っておくべきセキュリティ等を参照ください。
1について
よくわかりました
「重複確認に使用するフィールドにインデックスを作成してあれば」
なるほどそういう風にすると早いのですね。
ちなみに下記のようにして、20件が登録済み、30件が未登録という50件をループで処理すると重複のデータは$resultにエラーと入りますがその他の30件は正常に登録されます。
($hoge1 は PRIMARY KEY に設定しています)
こういうやり方は問題があるのでしょうか?
「動作に問題はないが極めて汚いコードだ」など厳しい意見でも構いません。
またこのようなことをやりたい場合の一般的な書き方も教えて頂ければ幸いです。
@$con = pg_connect(.....省略.....);
if($con == false){
print "error";
exit;
}else{
foreach($XXX as $value){
list($hoge1,$hoge2,$hoge3) = split("¥t",$value);
$result = pg_query(INSERT INTO table VALUES('$hoge1','$hoge2','$hoge3'));
}
}
pg_freeresult($result);
pg_close($con);
[(質問1)について]
2番目の回答のコメントにあるようなやり方は適切ではないと思います。
動作はするかもしれませんが、常にエラーが発生するわけですよね。
この処理のやり方では本当に問題があるエラーが発生しても、おそらくエラーに気づかないでしょう。
「または、一気に全てを登録してから重複データを削除する。」というのは2番目の回答のコメントにあるように、そもそも登録できないはずです。
また、PRIMARY KEY以外の項目の内容が変わることはないのでしょうか。
上記で言うならば、PRIMARY KEYの$hoge1に対する$hoge2、$hoge3の値が変わる可能性はないのか、ということです。
値の変更も考慮した場合、以下のように処理します。
参考情報ですが、MySQLでは上記の機能を簡単に行うためにREPLACE構文が使えます。
(このあたりがMySQLが好まれる理由なのかもしれませんね。)
[(質問2)について]
別の質問に対する回答でも書きましたが、pg_escape_stringやpg_escape_byteaを使ってDBに挿入する前に文字列を適切にエスケープしておく必要があります。
参考になれば幸いです。
ありがとうございます
やはり動作はするけど無茶苦茶なのですね。
> PRIMARY KEY以外の項目の内容が変わることはないのでしょうか。
これについてはありません。
* PRIMARY KEYをキーにしてレコードの存在の有無SELECT文で確認
* 存在しない場合はINSERT、存在する場合はUPDATE
やはり確認しながら登録していくのですね。
> MySQL REPLACE構文
これも勉強になりました。
> pg_escape_string
「データベースに挿入するための 文字列をエスケープ」と言うのがあったんですね。
ありがとうございました。
ありがとうございます
テキストファイルの内容を登録したいときは「copy」が良いようですね。
私はいつもタブ区切りのテキストデータを扱っていたのでエスケープは特に気にしていませんでした。
SQLではエスケープが必要なのですね。