VimとExcelを組み合わせて全く新しいSQLクエリーを生成する


2011年 07月 21日

問題

ソフトウェア開発はクリエイティブでエキサイティングなものではありますが、いつもそうだとは限りません。
時には泥臭い作業が必要になることもあります。

例えばとある企業で運用されている業務用アプリケーションのメンテナンスを任されていたとしましょう。
時折
「△△部署が○○部署と☆☆部署に分割されたので関連データを移行してください。
対応関係は添付のExcelファイルを参照してください」
のような依頼が舞い込んできます。
これが5個程度なら手作業でSQLクエリーを書いても構わないのですが、
さすがに1万と2千個くらいになると手作業ではやっていられません。
となると何らかの方法で貰ったデータからSQLクエリーを生成することになります。

しかしこのSQLクエリーの生成が案外面倒だったりします。
貰ったデータがCSVの場合、これが素朴なデータならエディターにコピーして適当に置換すればいいのですが、
クォートが含まれていたりすると置換する気力が失せます。
さらに大抵の場合、*.csvではなく*.xlsでデータを貰うことになります。
*.xlsの場合、セルの内容に改行文字が含まれていることがあるため、
これもCSVと同様に「エディターにコピーして云々」ということは簡単にはできません。

そうなるとExcel上でSQLクエリーを生成する方が簡単です。
例えば以下のようなデータが記載された*.xlsがあるとしましょう:

  • A列に関連データのID
  • B列に移行前の部署のID
  • C列に移行後の部署のID

この場合、D列に以下のような数式を入力すればSQLクエリーを生成できます:

="UPDATE Foo SET section_id = '" & C1 & "' WHERE id = " & A1 & " AND section_id = '" & B1 & "'"

しかし、このような数式を入力するのは結構面倒です。
本来実行したいクエリーは以下のようなものなのですが:

UPDATE Foo SET section_id = 'C1' WHERE id = A1 AND section_id = 'B1'

文字列連結が入り乱れて読み難くなっていますし、
生成したクエリーにミスがあった場合、
それを修正するのも一苦労です。
上記の例の場合はまだパラメーターが3つだけですが、
実際には10個や20個は普通に使うことになるため、
書き難さや読み難さはさらに大変なことになります。

どうにかしてこのようなSQLクエリーの生成を簡単に済ませられないものでしょうか。

解決方法

  1. operator-userをインストールします。
  2. 以下の内容をvimrcに追加します(キー割り当て(ox)は一例なので各自の好みに合わせて変更してください): map ox <Plug>(operator-excelize) call operator#user#define('excelize', 'OperatorExcelize') function! OperatorExcelize(motion_wise) let b = line("'[") let e = line("']") execute b ',' e 'substitute/\v(\''?)(\$?\u+\$?\d+)(\''?)/\1" \& \2 \& "\3/g' execute b 'substitute/^/="/' execute e 'substitute/$/"/' endfunction

これで、Vim上で以下のようなテキストに対して:

UPDATE Foo SET section_id = 'C1' WHERE id = A1 AND section_id = 'B1'

oxox などと入力すると以下のようにExcel用の数式に変換してくれます:

="UPDATE Foo SET section_id = '" & C1 & "' WHERE id = " & A1 & " AND section_id = '" & B1 & "'"

oxoperatorですので、
複数行に渡るクエリーを変換したい場合は oxipVjjjjjjjjox 等でできます。

これでデータ移行の依頼が多い日も安心です。やりましたね。

補足

  • operator-userを使えば簡単に独自のoperatorが定義できるので、
    今回のようにニッチなものが作り放題です。例えば
    「指定範囲内の数値らしき文字列の合計値を求める」ことや
    「指定範囲内の useusing 等の宣言を綺麗にソートする」ことが
    簡単にできるようになります。
  • arpeggio
    を利用すると「ox が同時に押下されたとき」などに機能を割り当てられるため、
    オレオレoperatorを定義しまくった場合でも安心です。
  • 次回はEmacs編です。