PostgreSQLについて幾つか教えてください。


(質問1)
数十秒から数分おきに50〜100件程度のデータを追加する際、通常はどのような流れで行うのでしょうか?
(追加しようとするデータには既に登録してあるデータも含みます)

例えば、1件ずつ登録済みかをチェックしながら未登録であれば追加登録する。
または、一気に全てを登録してから重複データを削除する。
など。。。

また、登録してあるデータの量にもよってその方法は変わるのでしょうか?


(質問2)
データを登録しようとする際「'」や「"」が含まれているとエラーになりますが、
「¥'」「¥"」とするとエラーは無くなります。
通常はそうするものなのでしょうか?

回答の条件
  • 1人2回まで
  • 登録:2006/05/28 22:39:03
  • 終了:2006/05/31 06:43:06

回答(3件)

id:kn1967 No.1

kn1967回答回数2915ベストアンサー獲得回数3012006/05/28 23:10:32

ポイント25pt

手順1)copyにてテキストファイルを丸ごと作業テーブルに読み込み

http://www.postgresql.jp/document/pg813doc/html/sql-copy.html

手順2)insertにて更新

http://www.postgresql.jp/document/pg721doc/reference/sql-insert....

カンマやクォートなどは区切り文字として使われるため、そこでデータが区切られてしまっておかしな事になってしまいエラーとなります。

そこで、カンマやクォートを本来の役割から外して(エスケープさせて)文字として認識させるために\を付けます。(\はエスケープ文字と呼ばれます)

id:worldtravel

ありがとうございます

テキストファイルの内容を登録したいときは「copy」が良いようですね。

私はいつもタブ区切りのテキストデータを扱っていたのでエスケープは特に気にしていませんでした。

SQLではエスケープが必要なのですね。

2006/05/29 17:34:48
id:pmakino No.2

まきのっぴ回答回数355ベストアンサー獲得回数282006/05/29 07:47:30

ポイント25pt

(質問1)

1回の登録件数が1件なら前者で良さそうですが、

多数のデータを一括処理するなら、1件ずつチェックしながら登録だと効率があまり良くなさそうです。

後者のようなパターンの方が効率が良いのではないでしょうか。

(追加途中に閲覧されると複数見えてしまって格好悪いことになるので、実際には登録から削除までを一つのトランザクションとした方が良いかと思われます)

ただ、どちらでなければならないと言うほど明確な違いは無いと思います。

(重複確認に使用するフィールドにインデックスを作成してあれば)


(質問2)

’等は SQL で区切りに使われる文字なので、エスケープしないと使用できません。

また、このことをよく認識したうえでプログラムを組んでおかないと、SQL インジェクションの脆弱性となり、深刻な被害を生むことがありますので、ご注意ください。

詳しくはIPA ISEC セキュア・プログラミング講座データベース編や、[ThinkIT] 第1回:Webアプリケーション開発者が知っておくべきセキュリティ等を参照ください。

id:worldtravel

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);

2006/05/29 17:48:22
id:bonlife No.3

回答回数421ベストアンサー獲得回数752006/05/31 06:31:49

ポイント50pt

[(質問1)について]

2番目の回答のコメントにあるようなやり方は適切ではないと思います。

動作はするかもしれませんが、常にエラーが発生するわけですよね。

この処理のやり方では本当に問題があるエラーが発生しても、おそらくエラーに気づかないでしょう。

「または、一気に全てを登録してから重複データを削除する。」というのは2番目の回答のコメントにあるように、そもそも登録できないはずです。

また、PRIMARY KEY以外の項目の内容が変わることはないのでしょうか。

上記で言うならば、PRIMARY KEYの$hoge1に対する$hoge2、$hoge3の値が変わる可能性はないのか、ということです。

値の変更も考慮した場合、以下のように処理します。

  • PRIMARY KEYをキーにしてレコードの存在の有無SELECT文で確認
  • 存在しない場合はINSERT、存在する場合はUPDATE

参考情報ですが、MySQLでは上記の機能を簡単に行うためにREPLACE構文が使えます。

(このあたりがMySQLが好まれる理由なのかもしれませんね。)

[(質問2)について]

別の質問に対する回答でも書きましたが、pg_escape_stringpg_escape_byteaを使ってDBに挿入する前に文字列を適切にエスケープしておく必要があります。

参考になれば幸いです。

id:worldtravel

ありがとうございます

やはり動作はするけど無茶苦茶なのですね。

> PRIMARY KEY以外の項目の内容が変わることはないのでしょうか。

これについてはありません。

* PRIMARY KEYをキーにしてレコードの存在の有無SELECT文で確認

* 存在しない場合はINSERT、存在する場合はUPDATE

やはり確認しながら登録していくのですね。

> MySQL REPLACE構文

これも勉強になりました。

> pg_escape_string

「データベースに挿入するための 文字列をエスケープ」と言うのがあったんですね。

ありがとうございました。

2006/05/31 06:41:46

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

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

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

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

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