DBサーバでUPDATE/DELETEを打つ安心感を高める
近年はDBサーバで直接UPDATE/DELETE文を発行する場面はかつてより減ったように感じますが、引き出しとして持っていて損はないと思ったので私が普段やっている方法をメモしておきます。
プロトタイピングだったり、開発環境でも有効なので手癖にしておくのは有効だと考えます。
MySQLを例に書いていますが、対象のRDBMSは特に限定されません。
1. 対象のレコードを下見する
まずはこれから更新する対象を見ておきましょう。
mysql> select * from books where id=1;
+----+-----------+-----------------+-------+
| id | author_id | title | price |
+----+-----------+-----------------+-------+
| 1 | 1 | Learning UPDATE | 4680 |
+----+-----------+-----------------+-------+
1 row in set (0.00 sec)
これで、まずは「今から更新しようとしている対象は本当に意図通りか」を確認します。
issueなどに作業記録を残しておく場合も、事前の状態を保存しておくと後から見た時に経緯が分かってよいです。
出てくる行数があまりにも多いとかだと厳しいけど、そういう場合はそもそも直接SQLを書いて更新しない方が安全かもしれません。
一応、更新をミスった時に場合によってはバックアップからの復元までしなくてもここからデータを戻せばいいか、みたいな安心感も得られます。お行儀は悪いけど、開発環境を壊した時に簡易的に復元したい場合はあるので。
2. トランザクションを張る
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
退路はなるべく確保しておきます。
3. 更新用のSQLを書く
3-a. コメントとして書き始める
mysql> #
途中で意図せずEnterを押してしまった時に何も起きて欲しくないので、コメントとして入力を始めます。
末尾のセミコロンを打つまでは確定されないとしても、そこだけで守られている状態はあまりにも怖いので、これで恐怖を和らげます。
3-b. where句から書き始める
mysql> #where id=1;
これも途中でうっかりEnterを押してしまった時のための対策です。範囲を限定せずに全レコードを更新してしまう事態を最初に避けます。
このwhere句をどう書くかはいくつかの選択肢があって、
- 1で発行したSQLをヒストリから拾ってくる
- 1で発行したSQLからコピペする
- 素直に手で書く
あたりが考えられますが、どうするかはお好みでどうぞ。
環境によっては事故防止のためにヒストリを残さないようになっているかもしれないし、クリップボードに意図しない物が入っていたり改行までコピペしてしまう可能性もある。環境と条件の複雑さに応じてリスクコントロールしましょう。
3-c. 残りの部分を書く
mysql> #update books set price=3280 where id=1;
後は普通に書いていって、意図したSQLが書けていることを確認します。
3-d. コメントを外す
mysql> update books set price=3280 where id=1;
これで完成。
3-e. ッターン!
mysql> update books set price=3280 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
実行されました。更新された行数は見ておきます。
4. 更新されたレコードを確認する
mysql> select * from books where id=1;
+----+-----------+-----------------+-------+
| id | author_id | title | price |
+----+-----------+-----------------+-------+
| 1 | 1 | Learning UPDATE | 3280 |
+----+-----------+-----------------+-------+
1 row in set (0.00 sec)
意図通りに更新されているかを見ます。意図せず他のレコードが変わっていないか不安な場合は周辺もお好みで見ておきます。
5. トランザクションを閉じる
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
ここまで問題なければcommitして完了です。その後の確認もすると思うけど、ここではスコープ外とします。
改めて念を押すと、この記事の主題は「こうすれば安全なのでDBサーバでガンガン直接更新かけていこうぜ!」ではありません。
とは言え、直接DBを更新する際に単にUPDATE/DELETE文を発行するのに比べれば安心感はだいぶ違うはずなので、選択肢として持っておくのは悪くないんじゃないでしょうか。
Discussion