仕事の流れがすらすら書ける!? 今すぐマジカランドへGo!!
■お知らせ
2008-01-22(Tue)
■[RDBMS]悔しさ垂れ流し(w

昨日「ちくしょー」とか書いて、おまけにそのせいでてっきりヤッターマンがあるのを忘れてて、さらに悔しくなって不貞寝したんですが、気を取り直してとりあえず今朝の体重が91kgと下降傾向にあるので、昨日のネタを晒しておきます。
どういうものかというと、あるテーブル(t_oyaとします)にレコードが入ったら、適当なタイミングで別のテーブル(t_koとします)に丸ごとピーコするというものです。そのためにログテーブル(t_logとします)を作って、何かあったらリトライできるようにするものです。割とありがちな処理ですね。ただ、こういう処理を一発のSQLで済ませてしまうのが見せ所(w
順番に書いていきます。尚、今回はPostgreSQL8.3b4です。
ストアドファンクションを作ります。
元と先でテーブルの列が一致していることが前提です。
最後に処理件数をreturnしてるのがミソ。
CREATE OR REPLACE FUNCTION setRecord(source_tbl_name varchar ,dist_tbl_name varchar ,id_col_name varchar ,record_id integer) RETURNS integer AS $$ DECLARE cmd text; cnt integer; BEGIN cmd := 'INSERT INTO ' ||UPPER(dist_tbl_name) ||' SELECT * FROM ' ||UPPER(source_tbl_name) ||' WHERE ' ||UPPER(id_col_name) ||' = ' ||record_id ; EXECUTE cmd; GET DIAGNOSTICS cnt = ROW_COUNT; RETURN cnt; END; $$ LANGUAGE plpgsql;
テスト用のテーブルを作ります。レプリケーションの親と子を想定します。
create table t_oya(c1 integer primary key, c2 integer, c3 varchar); create table t_ko as select * from t_oya;
親のほうに3件insertしておきます。
insert into t_oya values (1,100,'hoge') ,(2,110,'puni') ,(3,120,'huga') ;
ファンクションのテスト
select setRecord('t_oya','t_ko','c1',2); -- これは普通にOK select setRecord('t_oya','t_ko','c1',4); -- これはゼロ件でOK
子のほうを見るとばっちりです。
select * from t_ko;
ここで、ログテーブルを作ります。
create table t_log (id integer, table_name varchar, id_col_name varchar, record_id integer, repl_flg integer);
ログにレコードを入れます。1件目はさっきinsertした3件のうちの1件目を表現しています。2件目は空振りするはずです。
insert into t_log values (1,'t_oya','c1',1,0) ,(2,'t_oya','c1',4,0) ;
ここで、必殺バッチUPDATEの出番
どういうことかというと、
- 親から子へのコピー
- ログのフラグ変更
を同時にやるわけです。
ログのフラグ変更を外側のトランザクションにしてるのが妙味。んで、フラグの変更値としてストアドのreturnを使ってます。
update t_log set repl_flg = setRecord(t_log.table_name ,'t_ko' ,t_log.id_col_name ,t_log.record_id ) where repl_flg = 0 ;
子とログを確認。子は1件だけ追加されて、ログのほうは空振りした奴はフラグが0のままです。
select * from t_ko; select * from t_log;
ここでは子テーブルのほうだけ固定で指定してますけど、ネーミングルールだとか何だとかを詰めれば、もっとあれこれとやれますね。
・・・と、ここまでは順調だったんだけどね〜。あとは親テーブルにトリガをつけて、ストアドの中で分散DBのリンク先指定をすれば、リモートの親とログを見てローカルの子にコピってくる、つまりレプリケーションの出来上がり〜だったんですが・・・。dblinkにはがっかりだよ(w ということで、終わってしまったわけです。OracleだとDBリンク名をつけるだけでOKなんですけどね。仕方がないので別の方法を考える次第です。
まぁでも、普通だとレコードをカーソルFETCHしてぐるぐる回して最後にフラグを変更するっていうような、手続き的に考えることが多いんじゃないかと思うんですが、SQLに慣れてくると「要するにフラグが0のレコードを全部1にすればいいんでしょ」って集合でとらえて、1を返すための処理ってのを考えればいいじゃんって風になってきます。
あと、こういうのはプロダクト依存なSQLなので記事には書けないんですよね。だからSQLってのはモジュール化出来ないとか変な誤解が生じたりするんですけど、こんな風に関数化していけばOKなんです。そういうことの出来ないDBMSもあるってだけでね。
バッチ処理なんてたいていの場合、こんな感じでSQL一発で終りです。んで、この辺の副問い合わせ系のSQLはSQL書き方ドリルでしっかりと取り上げてますので、よろしければ是非(^^) ・・・と宣伝も交えながら、悔しみを晒しておくのでありました。誰かのお役に立てば重畳。
■[Life]asahi.com:倒す・殴る・からかう・動物に例える 柏原の障害者施設 - 関西

http://www.asahi.com/kansai/news/OSK200801210040.html
・・・切ないなぁ。
職員さんが大変なのは、同じく重度の妹を持ってお世話になっている家族として理解できるので、それだけに頑張ってほしいです。色々と書いたけどあとは消しておく。
■[仕事]連載:動画で配信!「現場で使えるREST」鼎談|gihyo.jp … 技術評論社

http://gihyo.jp/dev/serial/01/rest
・・・技評さんの晒し攻撃第二段キタ(^^; というわけで、WEB+DB PRESSのVol.42におけるREST特集の元ネタとなった鼎談の動画が公開されています。
いやね、正直ぶっちゃけめちゃくちゃテンパってます(^^; だって、当日の本番直前で「じゃ、仕切りは羽生さんで」なわけですよ。私は横で見聞きして「ふんふん」って言ってればいいんだと思ってたので、めっちゃ焦ったわけです。台本とかないし。こんなテーマに触れたいですね〜って事前にメールでやり取りしてたものをサマった紙が1枚あるだけ(^^;
で、仕方がないのでちょっとした技を使っています。要件定義や現状分析のときにお客様に対して行っているヒヤリングの手法です。私が現場でお客様のお話を伺う時は、ほぼこんな感じでやってます。普段と違うのはメモ取ったりホワイトボードにサマったりということをしていないだけですね。スキルは身を助く(w
何かもう途中で目が泳ぎまくってますけど、勘弁してください(^^;; ニコからコメントつけられるようですけど、もうほんとご容赦くださいm(__)m いや、俺頑張ったよ、きっと(^^;; 燃え尽きますたです、はい。
内容自体はかなり面白いと思います。羽生のところはすっとばして、ぜひご覧ください。