delete&insert するデータのIDを維持しなくてはならない ... のだろうか?
IDについてまだ考えている。
テーブルごとに必ずIDを振るという考え方に、まだ抵抗がある。
「今のところ誰も見ていないID」を振る意味が分からないのだが...
「誰も見ていないID」とは例えば、delete&insert で一括登録するレコードに付けたID。
マスタに多値従属する属性を切り出したテーブルで発生する。
ちょっと前に書いた例:
MO(=多値を外出ししたテーブル)にはIDを振らない。例えば社内システムで「社員がメールアドレスを
好きなだけ持てる」という場合、社員マスタに社員メールアドレステーブルを外付けする。これがMO。
こんなスキーマですね。
社員マスタ = { 社員ID(PK), 社員番号(UNIQUE), 社員名, ... }
社員メールアドレス = { 社員ID(FK), メールアドレス }
ここで、全てのテーブルに機械的にID列を付ける、というルールに従って、社員メールアドレスに「社員メールアドレスID (PK)」列を追加したら、
社員メールアドレス = { メールアドレスID(PK), 社員ID(FK), メールアドレス }
社員情報の更新時に微妙な問題を呼び込むことになる。
「IDはインスタンスのライフサイクルを示すもの」だとすれば
社員情報の入力画面が
- メールアドレスの入力欄がデフォルトで3つ取ってあって、追加ボタンを押すと入力欄が好きなだけ増やせるようになっている
- 全ての入力欄は等価で、例えば「最初の欄はPC用・次の欄は携帯用」といった区別はない
という場合、このフォームから送信されたメールアドレスは delete&insert で書き込みたい。
メールアドレスIDをIDENTITY型とかにして自動で振ならば、発行されるSQLはこんな感じ。
-- 一括削除 DELETE FROM 社員メールアドレス WHERE 社員ID=100 -- 挿入 INSERT INTO 社員メールアドレス(社員ID, メールアドレス) VALUES(100, 'aaa@example.com'); INSERT INTO 社員メールアドレス(社員ID, メールアドレス) VALUES(100, 'bbb@example.com'); INSERT INTO 社員メールアドレス(社員ID, メールアドレス) VALUES(100, 'ccc@example.com');
しかし、IDがデータのライフサイクルを示すものだとすれば、同じメールアドレスのIDは、更新前後で変わっていてはならないことになる。
更新前がこうだったとすると:
メールアドレスID | 社員ID | メールアドレス |
---|---|---|
1 | 100 | aaa@example.com |
2 | 100 | bbb@example.com |
"ccc@example.com"の追加後がこうなったら、IDの寿命がデータの寿命より短くなってしまい、ライフサイクルを表していることにならない*1。
メールアドレスID | 社員ID | メールアドレス |
---|---|---|
3 | 100 | aaa@example.com |
4 | 100 | bbb@example.com |
5 | 100 | ccc@example.com |
これならよい:
メールアドレスID | 社員ID | メールアドレス |
---|---|---|
1 | 100 | aaa@example.com |
2 | 100 | bbb@example.com |
3 | 100 | ccc@example.com |
だから、メールアドレスIDを自動で採番してはならない。... と考えるのは原理主義的か。そこまでこだわる必要はないのか。
しかし、そこにこだわらなかったら、この「誰も見ていないID」の存在意義は何だろうか。
こんなのは些末な問題だけど
何が言いたいのかというと、{ 社員番号, 社員名, 社員メールアドレス } という集合のライフサイクルを表現するのは社員IDだということ。
社員メールアドレスだけがメールアドレスIDでライフサイクルを表現されているわけではないということ。
その証拠に、社員を追加した時にメールアドレスは生成され、社員を削除したらメールアドレスも消滅する。
メールアドレスの追加更新削除は、社員名の変更と同じようなイベントであるということ。
*1:もちろんレコードのライフサイクルを表していることにはなる。それにどういう意味があるのかは分からないが...