プログラマのためのSQL 読書会(15)に参加
15章を読みました
プログラマのためのSQL 第4版 すべてを知り尽くしたいあなたに
- 作者: Joe Celko
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/19
- メディア: Kindle版
- この商品を含むブログ (11件) を見る
- 感想
- カーソル
- delete文ではtableの別名は使えない
- 遅延制約の使い道
- UPDATE文に行構築子が使える
- 主キーのないテーブルは結構ある。
- 論理削除と外部参照性制約
- 誤記?
- トリガーとcascade
- update非推奨派
- システム時間を表す予約語は色々なタイプがある。
- bulk insertは標準ではない。
- バルクロードはSQLを介さずにデーターを直接入れるAPIを使っている(多分)
- 交換のクエリは実装依存。
- オートコミットモードは怖い。
- 15.4ベンダー拡張が持つ欠陥について
- merge(upsert)
- ほか
感想
初参加です。本の読み具合はちょうど4割、と言うところ。 本書の日本語訳は第4版ですが、原著は5版まで出ているようです。
パフォーマンスとか内部の動きってどうしても「実装に依存する(キリッ」となり話が終わりがちですが、 参加者の皆さんの経験が豊富で、いろんな観点からの事例・各RDBMSの話を拝聴することができ、大変充実した2時間となりました。
私はDBスペシャリスト勉強中 + ミックさんが関わっている本を結構読んでる*1 くらいの知識なので、どれかのRDBMS固有のディープな知識はないので、色々知ることがありました(特にMySQL)
DB2とSQLServerのウェートは少なかったような? その2つ詳しい人が来れば面白いかもしれません。
ちなみにSQLiteの話は一度も出ませんでした
カーソル
本書にもカーソルを推奨していない書き方をしている箇所があったり、 カーソルは旧時代の遺物で使う必要のないものだと勝手に思い込んでいたので、思い切って聞いてみました。
- ストアドでは使った方が良い。
- 同じテーブルを何回もスキャンするようなクエリ
同じテーブルをなんどもスキャンしているクエリでは カーソルで処理した方が効率が良い、と言う説明は納得がいきました。
delete文ではtableの別名は使えない
DELETE FROM Personnel AS B1 WHERE Personnel.boss_nbr = B1.emp_nbr AND Personnel.salary > B1.salary;
FROM句でつけた名前を使った複雑な相関サブクエリは利用できない。
遅延制約の使い道
- テストデータの用意。
- バッチだと制約が重くなる。
遅延制約は以前から知っていたが、自分なりに感じていたメリットは レコードを削除させる順番に柔軟性を持たせられる・・・と言うもの。 これだとちょっと設計が雑な気がする。
バッチで処理中に一々制約のチェックが入ると重くなるので、 バッチに関しては遅延制約が有効とのこと。
UPDATE文に行構築子が使える
UPDATE Foobar SET (a,b,c) = (1,2,3) WHERE x < 12
右辺にクエリが書けるね、と言う意見がでた。 行構築子と言う言葉は知らなかった。調べてみたらテーブル構築子と言う単語もあるようだ。
主キーのないテーブルは結構ある。
主キーがないと、mysqlだとレプリケーションが死ぬ。。。 私も一度主キーのないテーブルを作らされたことがあるが、 主キーのないテーブルは案外多いらしい。
論理削除と外部参照性制約
論理削除フラグを使っているプロジェクトには参照制約が貼れない(活用できない)。
誤記?
15.1.5に
参照整合制約を使わずに複数のテーブルから削除する 1.削除する値を持った一時テーブルを使う。 2.参照整合制約のCASCADEオプションを使う 3.ビューまたは規定テーブルのINSTEAD OFトリガーを使う。
とありますが、2って結局参照整合制約使ってるじゃないか!と言う鋭いツッコミがありました。
トリガーとcascade
とあるRDBMSでは小テーブルのdeleteトリガーは、親テーブルの削除の連鎖をトリガーしない。
トリガーは色々問題を起こす。
トリガーはスタックを使いながらやるので、 大きなトリガーはトラブルのもと。
update非推奨派
そう言う派閥があると@makopi23さんに教えてもらいました。
http://makopi23.blog.fc2.com/blog-entry-176.html
システム時間を表す予約語は色々なタイプがある。
- トランザクションの開始時
- バラバラ
- 行の中では同じ。
- 列でバラバラ
- 文の中では同一になる。
SYSDATEくらいしか使ったことがないけど、ここはドキュメントをきちんと確認しようと思う。
bulk insertは標準ではない。
便利だが標準ではない。 https://qiita.com/bunty/items/91283160b0a38956655e
Oracleのbulk inertしか知らなかったが、MySQLならかなりシンプルに書ける。
バルクロードはSQLを介さずにデーターを直接入れるAPIを使っている(多分)
SQLがいちいちパースされないので、実行が早い。
交換のクエリは実装依存。
実際に主キーを交換するクエリは失敗するDBMSがあった。 MySQLは左から順番にやっていくため成功しないらしい*2
オートコミットモードは怖い。
オートコミットモードにもサーバー設定とクライアント設定がある。 過去にサーバー側でオートコミットモードを必ず使う必要のあったDBMSではクライアント側で設定していた模様。
最近私もオートコミットな職場で働いているが、検証環境とわかりつつヒヤヒヤしてしまう・・・
15.4ベンダー拡張が持つ欠陥について
最近は治っている。らしい
merge(upsert)
かなりシンプルにUPSERT文が使えるDBMSの経験があるので
「merge文って結局アプリケーション側のコードでおこなるINSERT or UPDATEの切り替えを SQLで書くだけで、実質クエリは2つ書かないと行けないし、ちょっと冗長な気がしますね。」
と発言したところ
- on dupulicate
- replace into *3
- effected rowsを教えていただいた。
mysqlは急進的?と言うか結構色々実験的なことをやっているらしい。
ほか
- temporaryはoracle由来。頑張って標準SQLにいれた。
- Oracleにはundo的動作をするflachbackクエリなるものがあるらしい