制約っていらなくね?at DB
制約っていらなくね? - 暇つぶし2ch2:NAME IS NULL
04/06/17 23:52 dpurb/Z2.net
Uze

3:NAME IS NULL
04/06/17 23:56 xzoV3ZXe.net
そう思うときもあるけど、それがあるお陰で、
データの整合性が取れてるって面もあると思う。
んが、そのデータの整合が取れてるっていうのが、目に見えて
実感できないから、「制約ってめんどいな」とは、正直思う。


4:NAME IS NULL
04/06/18 00:31 .net
糞っスレ

5:NAME IS NULL
04/06/18 13:40 Zpejz88K.net
>>1 は無知。

6:NAME IS NULL
04/06/18 14:11 .net
>>1を制約しろ

7:NAME IS NULL
04/06/18 19:43 .net
>>1
DB側で制御できたら、プログラム側で制御しなくて良いのだが。

8:NAME IS NULL
04/06/18 20:15 .net
ついでにストアドもイラネ

9:NAME IS NULL
04/06/18 22:23 Zpejz88K.net
>>8 はいはい。
おのれは、いずれホームレス^^

10:NAME IS NULL
04/06/18 22:36 .net
>>8はMySQLユーザー


11:NAME IS NULL
04/06/19 07:38 OHujBfWT.net
ただDBサーバーにアプリケーション機能を盛り込み過ぎるのもどぉーかなー

12:NAME IS NULL
04/06/19 10:10 iDH3OAyt.net
>>11
その方が効率的だから、そうするのだろうが。
dbをISAM(索引順編成ファイル)としか使ってないの?w

13:NAME IS NULL
04/06/19 16:32 .net
制約いらないよね。 いらないから使わなければいいだけのこと。
制約にひっかかるデータは事前にチェックして、どの部分がまずいのかを
使う側に明確に表示させたいからね。
そのままエラー内容表示させるのもダサいしね。

14:NAME IS NULL
04/06/19 18:26 .net
>>13
同意。
そもそも、制約に引っかかるようなデータを書き込むアプリは、作りがアレだとおもうが

15:NAME IS NULL
04/06/19 19:06 .net
>>13-14
ユニーク制約が、アプリ側でチェックできるんでつね?
重複チェックとは、別次元の問題だと思いまつが。。。

16:NAME IS NULL
04/06/19 20:25 .net
>>13
>使う側に明確に表示させたいからね。
>そのままエラー内容表示させるのもダサいしね。
制約違反はアプリにコールバックされるだろ
そこからエラーメッセージ出せばいいだけじゃん・・・

17:NAME IS NULL
04/06/19 22:40 rF590MRN.net
>>16
そうだよね~
あるマスタにないものを別のテーブルに入れてはいけない場合を考えてみよう
プログラムがそれをやるとなると
マスタの中に存在するか調べてから入れないといけなくなる
制約使えばエラーが発生するのでそこでメッセージ受け取って
適切なエラーメッセージクライアントに返すだけ
ただ、最近では制約とか外部キーとか使わないものを推奨している雰囲気はある

18:NAME IS NULL
04/06/19 23:25 .net
まぁ、あれだ。データベース設計やる奴とアプリ組む奴
がちゃんと意思疎通できる程度の規模のアプリなら問題
ないわけだ。大規模システムやアプリ開発を外注に出す
場合なんか、コミュニケーション不足やバグで整合性が
保たれないデータを作られないようにに、設計者がガー
ドの意味で制約を張るのは当然だと思うよ。


19:NAME IS NULL
04/06/20 00:14 .net
>>18
そういう意味で制約を使うのなら納得。
でも、エラー処理をまかせるってのは、どうなんだろ。
いまどきは、そういうもんなの?

20:NAME IS NULL
04/06/20 00:39 .net
>>19
>エラー処理を任せる
ここで言ってるエラー処理って
DBからエラー受け取って
エラーメッセージを振り分けて表示するだけのことじゃないかな?
実際、制約あればエラーあった時点でDB更新は無いわけだし
プログラミングは楽になる

21:NAME IS NULL
04/06/20 01:19 .net
 本来データの重複や規定外の値が入るのを防ぐのは内部スキーマの担当で、それを
外部スキーマにやらせるならば、作成するすべての外部スキーマが
エラーチェック->●エラーなら=>エラー表示してやり直し ●OKなら=>保存=>次行ってみよー
という機構をもつ必要がある。そうすると外部スキーマの処理数が増えてバグを作りこむ
可能性も上がり、万一ひとつでもエラーチェックが甘い外部スキーマがあればそれのために
内部スキーマに整合性エラーが出かねない。
 その点内部スキーマに持たせれば、外部スキーマは
保存->●エラーなら=>エラー表示してやり直し ●OKなら=>次行ってみよー
と、エラーチェックの結果を判断するだけでよくなって万一バグがあってもランタイムエラーで済む。
 アプリの作成中は良くても、今後増改築があったときにすべてのテーブルに対してどのような
データを入れてはいけないか、忘れてしまってひとつでもエラーチェックの甘いアプリを
作ったら後が悲惨そう。
 大体、もらったデータは例え候補キーが重複してたりNULLを含んでいても関係なく保存
していくDBMSって、「そこのコンビニ袋の中身冷蔵庫に入れといてくれよ」って言ったら
「うあぁぁ、カップラーメンも牛乳もガツンとみかんもみんな冷蔵庫に入れてあるうぅゥゥー!!!」
てなことするタコスケっぽくて情けなくない?

22:NAME IS NULL
04/06/20 01:40 .net
>>21
俺もなるべくならDBにやらせたい派だな
だってNullはDBの機能で入れられないようにするくせに
外部キー制約はプログラミングで実装ていうのはおかしいよな
ただ、ひとつだけ
もし、「あ、このデータ消したいな」と思った場合に困るんだよな
そうした場合には制約ないほうがいいし
事実そうしているプロジェクトが多い

23:NAME IS NULL
04/06/20 01:56 .net
>22
つ[ ON DELETE CASCADE ]
つ[ ON DELETE SET NULL ]

24:NAME IS NULL
04/06/20 07:02 .net
今年のTE(DB)の試験では制約がいっぱい出ました

25:NAME IS NULL
04/06/29 02:09 Pxx6PBqy.net
まあ、論理設計の意図を反映させる意味で制約はつけてるけど。
正直、ユニーク制約なんかはユニークインデックス付ける方がよくやる。

26:NAME IS NULL
04/07/08 13:48 .net
NOT NULLは大嫌い。
何度ユーザーに裏切られた事か。
業界標準コードがNULLの商品データとか
本番稼動後になってから平気で寄越したり。
そもそも画面から更新処理を行おうとした時点で
DB叩く前に入力チェックしなきゃいけないし。
未入力のフィールドにフォーカスあてたり
フィールドごとにエラー文言変えたり。
データはなるべく静的な物として捉えたいので
業務ロジックを盛り込む事は避けたいです。
ただ、ユニークや外部キーなどは
どちらかというとシステム寄りの要件なので
場合によってはつけた方がいいかなあとも
最近は思い直してます。

27:NAME IS NULL
04/07/08 22:36 .net
まぁシステムによりけりだね。
制約は断じて「業務ロジック」では無い。
でも設計がアレなシステムでは、制約が業務ロジック化してしまう。

28:26
04/07/09 10:17 .net
制約自体に罪はない、設計がアレなだけだ、って事ですね。
今まで誤解してたよ、ごめんよ、制約。
全てアプリ側でコントロールすると
>21みたいな事にもなるしね。
これからは心を入れ替えて制約も活用してみます。
皆さん具体的にどうですか?
制約使って便利だーいやトラブったーとかあります?
外部キーとかってどうしても使う勇気が湧かないんですよ。
ただ新しい事やりたくないってだけなんですが。

29:NAME IS NULL
04/07/10 18:41 +BBjcTFg.net
単にDBに値をチェックしてもらうだけならどうでもいいけど、関連レコードの自動削除みたいのはかなりいいと思うけどどうよ?
外部キーに ON DELETE CASCADE 付けとけば、親テーブルのレコードを削除するだけで紐付く子テーブルレコードも漏れなく削除できるよ。
ところで質問。
テーブルA とテーブルB があって、テーブルB はテーブルA の主キーを外部キーとして参照しています。
で、テーブルA のレコードに紐付くテーブルB が存在するかどうかを確認したいです。
できれば参照されている件数なんかも知ることができるといいです。
SELECT なりでも調べられますが、実は実際に扱おうとしているものは、テーブルA の主キーを外部キーとするテーブルがべらぼうに多くて、ちょっと大変です。
こんな感じになっちゃいます。
SELECT
  TABLE_A.ID,
  (SELECT COUNT(*) FROM TABLE_B WHERE TABLE_B.ID=TABLE_A.ID)
  +(SELECT COUNT(*) FROM TABLE_C WHERE TABLE_C.ID=TABLE_A.ID)
  +(SELECT COUNT(*) FROM TABLE_D WHERE TABLE_D.ID=TABLE_A.ID)
   :
   :
FROM TABLE_A

やりたいことってのは、どこからも参照されなくなった テーブルA レコードを削除したいのです。
なんかいい方法ありますか?


30:NAME IS NULL
04/07/10 19:04 .net
大変つっても一回書きゃおしまいだろ?

31:NAME IS NULL
04/07/10 19:09 .net
>>30
処理にかかるコストの問題です。


32:NAME IS NULL
04/07/10 21:46 .net
>>29
TABLE_A.IDに ON DELETE NO ACCTION 付けて全行削除してみればいいんじゃないの?

33:NAME IS NULL
04/07/10 21:55 .net
コストの問題なら、>>29でどのくらい問題なのか書かんと。

34:29
04/07/10 22:20 .net
>>33
現在はまだ実験してる段階なので、実際どのくらいの処理時間になるかはわかりませんが、やろうとしていることは次のようなものです。
このテーブルAはちょっとしたログテーブルみたいなもので、トランザクション毎に一行 INSERT されます。
で、そのトランザクション内で更新されたいろんなテーブルのレコードには、その TABLE_A.ID を記録します。
だからほっとくとテーブルAレコードは無限に増えて行きますし、TABLE_A.ID を外部キーとするテーブルの数も数十個あります。
また、更新を繰り返すうち、古いログ情報はどのテーブルからも参照されなくなるので、そうなったときには削除しなくてはなりません。
各テーブルの規模は、数十件くらいのものから数万件を超えそうなものまで様々です。
だから、>>29 にある SELECT で逐一被参照数をカウントするのは、ちょっと具合が悪そうだと推測できます。
まあ、必ずしも数を数える必要性は無いので、COUNT しようなんてことはせずに EXIST で各テーブルの参照の有無を調べて
ばっさり DELETE してしまってもいいですが、WHERE には結局数十個のテーブルについての EXIST が並ぶことになり、
パフォーマンスは悪そうです。
DBの内部では、外部キーに参照されたレコードが削除されるときに、そのことを瞬時に把握する仕組みを持っているはずで、
それをなんとか利用する手段は無いのかと思っています。
ちなみに DB は PostgreSQL です。
システムテーブルについてもあれこれ調べてみたのですが、今のところめぼしい発見はありません。
テーブルAに被参照カウントを持って、各テーブルが更新されるときにトリガを使ってカウンタの自動更新をすることも考えましたが、
PostgreSQL はトリガ関数をお手軽に作れないようなのでちょっとアレです。
>>32 の内容はよくわからないのですが、テーブルAの全行を無条件に削除したら削除できないものだけ残るって
やり方があるなら、そういうアプローチでもOKです。
ところで >>32 の ON DELETE NO ACCTION って、TABLE_A.ID につけるものじゃなくて、他のテーブルの外部キーに
付けるものではないのでしょうか。
で、NO ACTION が指定されてると、削除しちゃいけない行を削除したときにはエラーになって処理してもらえないと思いますが、
ちょっと勘違いしてますかね?


35:29
04/07/10 22:59 .net
自己レスです。ちょっと思いついちゃいました。
テーブルAを参照する外部キーを、それ専用のテーブルにして、他のテーブルはそのテーブルを INHERITS すれば
具合がいい気がしてきました。
こんなかんじ。
CREATE TABLE_A (
 ID INTEGER PRIMARY KEY,
 DATA TEXT
);
CREATE TABLE_FK (
 FK INTEGER NOT NULL REFERENCES TABLE_A(ID)
);
CREATE TABLE_B (
 SOMEDATA TEXT
) INHERITS(TABLE_FK);
CREATE TABLE_C (
 SOMEDATA TEXT
) INHERITS(TABLE_FK);
そうすると、削除 TABLE_A の削除は
DELETE FROM TABLE_A WHERE NOT EXISTS(SELECT 1 FROM TABLE_FK WHERE FK=TABLE_A.ID);
みたいな感じですかね。
シンプルで速そうな気がしますが、いかがでしょう?
でも、外部キーに参照されてるレコードなのか否かの判定方法は知りたいので、知ってる人がいましたらよろしくです。


36:29
04/07/10 23:18 .net
たびたびすみません・・・
>>35 のやり方だと、TABLE_FK の外部キー制約は TABLE_B や TABLE_C に継承されないっぽいです。
TABLE_B、TABLE_C それぞれで外部キー制約を付ける必要があるようです。
ハマるところだった・・・
危ない危ない。


37:名無しさん@そうだ選挙に行こう
04/07/11 09:19 .net
>ばっさり DELETE してしまってもいいですが、WHERE には結局数十個のテーブルについての EXIST が並ぶことになり、
>パフォーマンスは悪そうです。
数十個といっても加算的なものだし。
逆にテーブルが3個しかないなら期待するパフォーマンスが出る
という保証はないから、まずは計測してみれ。
>>34を読む限りでは、テーブル3個の場合のパフォーマンスにも
満足できなそうに思えるんだが。
>DBの内部では、外部キーに参照されたレコードが削除されるときに、そのことを瞬時に把握する仕組みを持っているはずで、
ふつう、そんなものはない。
ON DELETE CASCADEも結局、トリガで対象のテーブルから
deleteしてまわっているのと違いはない。

38:29
04/07/11 10:23 .net
>>37
すみません、まだ計測できる段階じゃなくて・・・
もちろんテスト用にデータがそろえば計測してみます。
だけど、NOT EXISTS が AND でいっぱい並ぶってことは、削除対象レコードであることがわかるためには
対象テーブルの全行を全検索することになるので、どうなんだろうと思うわけです。
INDEX 付ければ速くなるでしょうが、ログテーブルを逆引きするためにいちいち INDEX の領域とるのはなぁ、
と躊躇してしまいます。
といってもそれは、他になにか手段があるはずだと思ってるから、選択肢として後回しにしてるに過ぎない
のですが。
>>DBの内部では、外部キーに参照されたレコードが削除されるときに、そのことを瞬時に把握する仕組みを持っているはずで、
>
>ふつう、そんなものはない。
そうなんですかね?
ON DELETE CASCADE 指定されたときはいざ知らず、ただの外部キーにより参照されてるカラムは、内部的に
被参照カウンタでも持ってるんじゃないかな、と勝手に推測したのですが。
というのは、>>35 のやり方をやったとき、
TABLE_FK には当然 TABLE_A に無い値は INSERT できないし、逆に TABLE_FK にある値は TABLE_A から削除できません。
これは期待する動作ですよね。
ところが TABLE_FK を継承した TABLE_B、TABLE_C へは、 TABLE_A に無い値でも INSERT できてしまいます。
で、TABLE_FK を SELECT してみれば、やっぱり TABLE_A に無い値を持つレコードができてしまっています。
たとえばその値が 100 だったとして、関節的にTABLE_FK に TABLE_A に無い 100 を INSERT して、次に TABLE_A に
100 を INSERT して、さらに TABLE_A からその 100 を DELETE してみると、TABLE_FK に 100 を持つ値があるのに
DELETE できてしまいます。
ということは、TABLE_A が削除されるときに、外部キー参照しているテーブルをいちいち検索しに行ってるわけでは
ないのかな、と思ったのですが、いかがでしょう?
しかし、継承させたテーブルで継承元の制約が受け継がれないってのは、一般的な仕様なのでしょうか。
それとも PostgreSQL のバグですかね?


39:名無しさん@そうだ選挙に行こう
04/07/11 12:15 .net
>>38
TABLE_B.IDとかには当然indexを設定していると思っていたんだが。
>INDEX 付ければ速くなるでしょうが、ログテーブルを逆引きするためにいちいち INDEX の領域とるのはなぁ、
本当にdeleteのパフォーマンスが問題ならindexを作る。パフォーマンスを
犠牲にしてでも領域を節約する必要があるなら作らない。
ディスク領域を気にしているようだが、じゃあこれらのテーブルにどのくらいの
レコードが登録されてどれくらい領域を必要とするか見積もってる?
チューニングの話なら「遅そう」「領域食いそう」とかの感覚的な話じゃ
先に進まないよ。そのへん見積もれないうちから小手先のテクニックを
弄しても無駄に終わる可能性が高いから、まずは正攻法でやってみれ。
>ということは、TABLE_A が削除されるときに、外部キー参照しているテーブルをいちいち検索しに行ってるわけでは
>ないのかな、と思ったのですが、いかがでしょう?
FKとB、Cは別のテーブルであって、FKをselectした際にデフォルトで
BとCも一緒に検索してるだけ。Aにない値がFKに入ったわけではない。
>しかし、継承させたテーブルで継承元の制約が受け継がれないってのは、一般的な仕様なのでしょうか。
>それとも PostgreSQL のバグですかね?
「一般的な仕様」などはない。それはバグじゃなくてPostgresの仕様。
たしかに、継承するなら制約やトリガなども継承された方が便利だと
思うんだけどね。

40:名無しさん@そうだ選挙に行こう
04/07/11 16:54 .net
>>29
もう少し手短にまとめてくれ。読むのがめんどくさい。
一般的に速度と記憶域はトレードオフ。実際に手を動かさずに、いつまでも机上の
空論を弄んで、根拠のない妄想に見切りつけずにあれこれ悩むのは時間の無駄。
そもそも更新速度の低下でならまだしも、記憶域を圧迫する理由でインデックスを
張るのを躊躇するような貧相な環境なら、まず環境を見直すべき。


41:29
04/07/12 02:30 .net
>>39,40
文章得意じゃなくて、端的に書けなくてスマソ。
INDEX を張るのを躊躇した理由は、容量の問題だけではなくて更新時のパフォーマンスも気にしてのことです。
さらに言うと、実はTABLE_A.ID への外部キーは、一つのテーブルあたり挿入時用、更新時用、削除マーク用の 3つあるので、
容量もINDEX更新のコストも3倍かかりそうで、なおさら気になったのです。
自分はINDEXに必要なディスクスペースや、INDEX更新に必要なコストを見積もるスキルは無いのですが、せっかく制約の
スレを見つけたので、制約に関する便利機能なんかの意見をもらえるかな、と思っての質問でした。
自分でも結局は INDEX 張って正攻法でやることになるんだろうな、と思っています。
> たしかに、継承するなら制約やトリガなども継承された方が便利だと
> 思うんだけどね。
ですよね。
そのほうがエレガントだと思うんですけど、PostgreSQL 7.0 から 7.1 への変更に「継承先のテーブルの継承列で主キー,
外部キーが定義できるようになりました.」とあるので、やっぱり仕様として意図的にこうなってるんですよね。
ところで
> FKとB、Cは別のテーブルであって、FKをselectした際にデフォルトで
> BとCも一緒に検索してるだけ。Aにない値がFKに入ったわけではない。
EXPLAIN で TABLE_FK をSELECT するクエリプランを見てみたら、本当に TABLE_B、TABLE_C の SELECT も
やってるんですね。
実はテーブルの継承って言葉はここ2~3日で覚えたので、新しい発見だらけです。
このスレで話してよかったです。
でも、ということは、INDEX を継承元テーブルに張るだけではなく、それを継承するテーブルにも INDEX を張らないと
ダメなんですね?
うーん、めんどくさいなぁ・・・
そう思うと、テーブルを継承するメリットってなんなんでしょうかね?


42:NAME IS NULL
04/07/21 01:04 .net
制約やデフォルト値を細かく指定しておくと
ドキュメントがないとか,前任者が遁走した時の場合でも
ある程度何をしたかったかがわかるのでよい

43:NAME IS NULL
04/07/21 10:57 .net
>>42
うんうん、わかるわかる(泣)。
俺、火消し役ばっかりやらされてるんで。
でも、遁走するような奴の設計には
懐疑的になってしまうのもまた事実ですね。
でも何も無いよりいいか。

44:NAME IS NULL
04/07/21 11:11 .net
適当な設計やっても平気で提案できるくらいの奴は、
神経が図太い場合が多いから、逆に辞めない。
間違った仕様を正したいのに、認められなくて
耐えられなくなって辞める奴の方が多い。
憎まれっ子世にはばかる。

45:NAME IS NULL
04/07/21 11:12 .net
関係ないけど、火消しを入れる予算があるのなら、
最初から出火させない人を雇えよと思ったりもする。
火消し担当の人が、最初からプロジェクトに関わればいいのに。

46:NAME IS NULL
04/07/21 11:22 .net
>>45
自然発火とか

47:NAME IS NULL
04/07/21 16:48 .net
>>45
そういった事が出来れば火消しなんか使わないかと。
むしろ火消しが出来る人(又はグループ)を
予備選力としてヤバい所に投入ってのは防御の基本かと。
(史実の重戦車大隊みたいだな)


48:43
04/07/21 18:53 .net
>>45
あたくしの場合、火消し役やらされてる間も
他の案件の保守で人月工数出とるんで
コストかかっとらんのですわ。
だから便利に使われるって訳です。疲れた・・・・。

49:NAME IS NULL
04/07/21 19:32 .net
納期間に合わなさそう

新しい人材を大量投入

スキル高い人の手間が、新しい人への引継や教育に取られる

さらに炎上

こういうパターンが多いよな。

50:NAME IS NULL
04/12/01 18:41:41 .net
うちでは、主キー以外の制約はってません
それはISAM的なんでしょうか?
なんかDBMSの機能を使ってるきがしない
関連削除も不具合が発見されてから、整合性調整アプリを作ってるし
みんなはきちんと関連図みたいなんカタメテからやってるんですよね?

51:NAME IS NULL
04/12/02 18:05:14 .net
実はうちもです。
カスケードってなーに?
頑張ってアプリ側で実装ですよ。

52:NAME IS NULL
04/12/15 07:00:38 6kA6XGLm.net
このスレっていらなくね?

53:NAME IS NULL
04/12/15 23:47:32 .net
あとから設計見てどういう意図で組んだのかわかりやすいから制約は付けてるなあ
どーせ突っ込む前にデータチェックするんだけどね

54:NAME IS NULL
05/01/04 23:49:35 gtuR+WFj.net
制約かぁ・・・
参照性合成制約とかトリガーによるチェックはどうかと思うが、
主キーとNOT NULL制約は最低限付けた方が良いな。


55:NAME IS NULL
05/03/29 17:51:13 .net
1 WEBからデータ入力(クライアントでのデータチェック)
2 サーバプログラムで加工(サーバでのデータチェック)
3 DBに格納(DBMSでのデータチェック)
なんかもどかしい.

56:NAME IS NULL
05/07/27 11:06:36 rghdAW4Q.net
保守する時に、
参照整合性制約サイコー。
トリガーは糞。
と思う事が多いのだが、
どうか?

57:NAME IS NULL
05/07/27 13:59:40 .net
>>56
参照整合制約って使った事ないけど
保守する上でどうサイコー?
本で読むような利点じゃなくて
現場の濃い話希望。

58:NAME IS NULL
05/07/28 10:46:45 KXoQY93/.net
売春婦(DB)とその客(アプリ)に例えれば・・・。
入れるときに相手にゴムの着用を求めても、それが万全とはいえないし、そもそもつけるかも強制できない。
そうであれば、自分で制約(避妊手段)を準備しておくのが、変なデータを作らないための予防策。

59:NAME IS NULL
05/07/28 18:55:51 .net
>>57
56じゃないが俺はゴミが入らないのが利点だと思う。
これ以上でもこれ以下でもない。
ありえないデータが入ってるDBなんざみたくねぇ!!
トリガーは便利だと思うけどな。
そのありえないデータを削除したりするのによく使う。

60:NAME IS NULL
05/07/28 23:56:28 .net
トリガーって、ER図から読み取れないから怖いやね。
時刻更新とか、極簡単で引継ぎしやすい物であれば便利だと思う。
スパープログラマな人が、作ったオレサマトリガーは、簡便∩( ・ω・)∩

61:NAME IS NULL
05/07/29 00:17:42 .net
参照整合性制約を張るとインデックスが張られるやね。
そのER図をプログラマに配っておけば、自然とコチラの意図通りの
インデックスを使ったSQLを書いてくれるといいなぁ。。。
(そこそこのレベルの人なら分かってくれる。)
他には、
・参照整合性制約に基づいた連鎖更新・削除が便利。
・Access2003のXMLエクスポート機能を使う場合に
 参照整合性制約に基づいて親子テーブルを
 エクスポート出来るとか。
中小規模で、レスポンス性能とかシビアでなければ
参照整合性制約付けといた方が管理しやすいと思う。
問題になれば、外すだけで性能アップさせましたと
言えるかもしれないし。。( ̄ー ̄)ニヤリ

62:NAME IS NULL
05/07/29 00:18:49 .net
現場の濃い話って、↓こんなのか?
中小SI ヘッポコシステム
客「このデータ消したいなぁ」
担「何度も申し上げた通り(略」
客「前の担当者なら(略」
上司「ヤレ!」
担「しかしDBを直接弄るのは、(略」
上司「この辺のデータを(略」
担「...」
客「データがオカシイゾ(略」
上司「誰がそんな事をヤレと(略」
担「...」

63:NAME IS NULL
05/07/29 12:22:38 .net
>>59
ゴミの排除を制約に全部まかせちゃうんですか?
恐いなーと思って。
何がゴミかとかありえないデータかってのは
業務要件だったりする事が多いわけで
それはアプリ側で実装されてた方がわかり易いし
管理も楽だと思うんですよ。
で、制約をつけると、再実装になるし
保守も難儀な事になりそう。
そうでもないのかな?

64:63
05/07/29 12:27:28 .net
あ、煽ってる訳じゃないです。
制約に対する偏見なのかなあって
ちょっと思ってきては居るんで
背中押してもらいたいというのが本音。
>61の連鎖削除・更新も
業務要件だからアプリで実装したいんですよねぇ。
トリガーもそうなんですが。
ださいのかなー。
あっ、でもレスポンス向上の一手に使えるってのは
いいっすね!そういうかわいい悪どさは好きです。

65:NAME IS NULL
05/07/29 13:13:32 ug+wSNY+.net
>>63-64
直接引用じゃなく、要点絞って記述するね。
>アプリで実装するほうが判りやすくて楽
1つのテーブルに対する処理が10個も20個もあるアプリで、
全ての処理が正しく動作することを補償するのは楽でしょうか?
NOT NULLの制約もないDBとか最悪ですよ。
>制約をつけると再実装
逆です、制約がまず実装でアプリ側が再実装。
アプリ作るのに、DB設計もせずに始めるのでしょうか?
で、トリガーと制約は別問題。
論理的制約をトリガーで実装するってのはあるけど。
主キーもない、NULL制約もないDBなんて、DB使わないでファイルに書けばいいじゃん。w


66:NAME IS NULL
05/07/29 13:48:36 ZZgow+OE.net
火と大杉で見れないよ

67:63
05/07/29 14:08:49 .net
>>65
まず具体的にNOT NULL制約に話なんですが、
業務要件としてNOT NULLなものって
アプリ側で入力チェックしますよね。
アプリ側の実装はどうしても必要になっちゃう。
で、そういうチェックはユーティリティクラスとかヴァリデーターとか
そんな風に共通化する訳です。
1つのテーブルに対して10個も20個も処理があったとして
アプリ側の設計で実装は1つにまとめられると思います。
で、ままあるんですが、当初NOT NULLだと思ってたのが
実はNULLもあるんだよーなんて突然お客様に言われた時に
アプリ側で仕様が把握し切れればいいんじゃないかなと思っちゃう。
>アプリ作るのに、DB設計もせずに始めるのでしょうか?
DB設計は事前にしますよ。ER図も書きます。
でもそれは論理設計と言うか概念設計です。
実際にDBを構える時はまた考え直します。
概念設計において業務要件を反映した制約を
そのまま実装としてDBに入れるか、
アプリでやるかって所だと。
ちょっと話はずれますが、
概念設計と実装で構成が違うのは当たり前にやってます。
特に識別子の考え方。概念では識別子は業務に沿って考えます。
だから「注文番号 + 行番」なんて複合キーもガンガン使います。
でも実装では、「注文明細ID」をキーにします。
勿論、一意制約とインデックスは「注文番号 + 行番」につけますけど。
だから、参照整合やNOT NULLに関しても
実装ではぶいてアプリで実装ってのにあまり抵抗がないのかも
知れません。
うーん、書いてて自分の強い優位性が見出せぬ。
過去の振り返りにしかなってない・・・わはは。
レス有難う御座います。長文失敬でした。

68:NAME IS NULL
05/07/29 14:33:29 ug+wSNY+.net
>>67
> 業務要件としてNOT NULLなものって
> アプリ側で入力チェックしますよね。
> アプリ側の実装はどうしても必要になっちゃう。
> で、そういうチェックはユーティリティクラスとかヴァリデーターとか
> そんな風に共通化する訳です。
アプリでの入力チェックとNotNull制約では、後者のほうが広い意味です。
入力チェックしても防げないバグデータでも制約で防げます。
それに、アプリを通さないDBテーブル同士でのデータ登録とか更新もありますし。
> 1つのテーブルに対して10個も20個も処理があったとして
> アプリ側の設計で実装は1つにまとめられると思います。
クラスなど実装が1つにまとめられることと、SQLの種類が複数になることは別問題ですよ。
その各パターン毎の更新などに対して、不慮の事故などをどのようの防ぐのですか?
全てのパターンを1つの汎用SQLで行った場合にしても、それらのパターン毎の試験は必要です。
> 概念設計において業務要件を反映した制約を
> そのまま実装としてDBに入れるか、
> アプリでやるかって所だと。
DBの責務としての制約はDBでやるべきだし、アプリの制約はアプリでやるべき。
それに、DBが常にアプリを通して更新されるとは限らないし。
メンテとか、後の修正や他システムとの連携などで、そのアプリに対する制約を相手に望めますか?
> うーん、書いてて自分の強い優位性が見出せぬ。
> 過去の振り返りにしかなってない・・・わはは。
だって、便利な機能を否定して茨の道を歩んでるから。
両方制約すればいいんですよ、DBとアプリの独立性を高めて考えて、それぞれの責務を課す。
DBは自分の入れられたくないデータを制約し、アプリは他に出せないデータは出さない。

69:63
05/07/29 15:35:16 .net
>>68
うーむ、茨の道、耳が痛いです。
やっぱりやった事ないから恐いってだけなんでしょうかね。
有難う御座います。
確かに、アプリを経由しないデータ連携などではお手上げですね。
最初からそんな要件なければいいですが
案件ごとに制約の実装方法がDB or アプリで
バラバラになっちゃうのも気持ち悪いですし
ポリシーとして最初から統一しちゃう方が、確かに安心。
あと、DBからの制約のエラーと
アプリでのエラーメッセージのマッピングで
困った事とかないですか?
DBからのエラーコードじゃ判りきらんよ、とか。
それも気になる所なのです。
柔軟にメッセージを対応させたきゃそれこそアプリの責務で、
アプリ側でチェックすれって所でしょうか。

70:NAME IS NULL
05/07/29 15:52:26 6uLcICyZ.net
DBから見たら制約を課すことまでが責務であって、その結果を返すだけだよ。
そのエラーをアプリがどう料理するかはアプリの実装の問題。
特定のエラーコードに意味を求める(キー重複など)場合はそのコードで分岐して処理すればいいし。
NULL制約違反ってのはあまり出したくはないよね。
やっぱ、アプリで事前チェックして、そもそもINSERTなどを投げないようにしたい。
Oracleとかだと、どのカラムで何のエラーってメッセージはもらえるけど、あくまで文字列情報だし、
貴方が悩むところはなんとなくは判ります。
そもそもとして、DBに制約をつけるのってそんなに大変か?w
Check制約にしても、そんなに手間じゃないでしょ。

71:63
05/07/29 16:07:46 .net
おっしゃる通り、別に大変でもないですよね。わはは。
飛ぶのが恐いわけじゃない、落ちていくのが恐いんだ
by 寺山修司
って心境です。
派手にバグを出してデータパッチわんさか当てなきゃーとか
なった時に、参照整合とかで苦労しないかなーとか
勝手に妄想してるのです。
次は飛んでみるかな。

72:NAME IS NULL
05/07/29 16:21:06 6uLcICyZ.net
>>71
想定してる場面が発生する原因は・・・。
1)システム分析が甘く、DB設計が間違っている為、実情に合わない制約をDBに課した
2)そもそもの業務がフレキシブル(w、なので、その時点での制約が邪魔になる。
のどちらかだと思うが。
前者であれば技量を磨くしかないし、後者はそもそも制約を付与する設計がやっぱり間違っているともいえる。
制約って基本的にはきつく課しておいて、緩めるときに本当に緩める理由があるか考えるほうが安全だよ。

73:NAME IS NULL
05/07/29 23:47:30 .net
>>64
連鎖削除・更新は、注文-注文明細とかで考えると、
業務要件では無くRDB側の物理実装時の都合だと思う。
と、言いつつも管理が面倒なので、アプリ側に実装させて
自分がDBを直接弄る場合にのみ、一時的に有効にするのが
オレサマのやり方だな。

74:NAME IS NULL
05/07/29 23:56:57 .net
NOT NULLの制約については、文字型について
Oracleと、SQLServerで扱いが微妙に違うのがイタイな。
Oracleは、NullとEmptyの違いが無いのに対して
SQLServerは、NullとEmptyを明確に区別する。
そのため、ほとんどのフィールドは、Nullを許可しているな。
考え方は、SQLServerの方が好きだな。
他の、DBってどうなのだろう。。?

75:NAME IS NULL
05/07/30 00:17:52 .net
さんざん書かれているけど、基本的な考えとしてアプリケーションありきの
モデリングを行うのは、後々の拡張性とか考えると嫌だな。
↓ちょうど良い記事を見つけた。
データは安定している ~POAからDOAへ
URLリンク(pcweb.mycom.co.jp)
所で、
制約の管理とか、モデリングツールにより
かなり効率が違ってくると思うのですが、
何かつかってます?
漏れの場合は、Erwin3.5使ってて
最近は値段の関係から、ER/Studioに移行させられそう。。。


76:NAME IS NULL
05/07/30 00:31:04 .net
うちはOBERです。
そーんなに使い勝手いいとは思えないかな・・・。

77:NAME IS NULL
05/07/30 06:07:29 .net
チラシの裏最強!

78:NAME IS NULL
05/07/30 09:53:03 .net
>>77
どの辺がチラシと思った?

79:NAME IS NULL
05/07/30 22:52:42 .net
>>74
DB2もPostgreも区別するよ。
つーかOracleが特殊なだけな気がする。

80:NAME IS NULL
05/07/31 02:33:05 .net
>>78
日記の裏でなくて
モデリングツールなぞ
チラシの裏で十分です
って話でそ。

81:NAME IS NULL
05/07/31 03:00:10 .net
>>80
そういう意味か。。
制約の保守が~、といった話が出ていたので、
その流れのつもりだったんだけどな。
漏れは、Erwin様にDDLだとか、管理してもらっているので、
モデリングツール無くなると、作業効率がた落ちなんだな。
DB自体と物理モデルの完全比較とか、使いこなすまでが
大変だけ使いこなすとスコブル便利だよ。
もう、手動で管理する自信ありませんぜ。

82:NAME IS NULL
05/07/31 03:03:30 .net
>>79
なるほどね。
サンクス!

83:NAME IS NULL
05/08/01 05:30:05 .net
>>81
モデリングツールは設計ツールじゃなくて保守ツールと考えると納得いく。
設計は紙と鉛筆が基本だけど、後のことを考えてあえて手間ひまかけてツールを使う。
だから保守をやらない開発メンバーには評判が悪かったりする。

84:NAME IS NULL
05/08/01 10:31:03 .net
そうなのか、評判悪いのか。。
漏れは中小規模な案件が多いせいか、
引き継ぎと言う事例が少ないだけで(~-~;
しょうがなしに保守や改善対応している
開発よりのタイプなんだけどな。
そういえば、UMLっぽい物をVisioで
書こうとした時はメンドクセと思った。
あんな感じなのかな。

85:NAME IS NULL
05/08/01 10:48:40 .net
「保守を行わない開発メンバー」という
箇所を見落としてた。
とはいえ、統一したフォーマットの
DDL書いてくれるだけでも便利だと
思うのだけどな。
そういった観点か既に保守する立場と(略

86:NAME IS NULL
05/08/01 12:08:59 .net
チラシの裏書いた本人だが、終盤はモデルツールでやりますよ。
ただ、概念から順次ツールに合わせて落としていくっていうのがどうも制限になって嫌で。
手法の1つとしてはツールの手順でもいいけど、設計ってそこまで理想的に出来ないこと多いし。
とりあえずの概念設計とかはチラシの裏というか裏紙が一番いい。


87:NAME IS NULL
05/08/01 22:58:35 .net
そのままの意味だったとは。。。
そいつぁ 盲点だたよ (^ ^ ;

88:NAME IS NULL
06/06/08 23:51:07 .net
ここで書き込んでいる人たちはずいぶん専門的な話題が多いようですが、
具体的にいったいどんな規模のどんなシステムに関わってるんでしょうか??
ここでいう「中小」とはどれくらいのものを指すんだろう・・・。

89:NAME IS NULL
06/06/30 00:59:24 .net
中…1000万行程度、数十テーブル程度で同時接続ユーザ数100人程度
小…100万行程度、数テーブル以下で列数最大20-100列、同時接続ユーザ数数名程度

90:NAME IS NULL
06/08/05 00:40:54 .net
今やってるのは
100万行程度、数百テーブルで列数最大100列、同時接続ユーザ数数名程度
ですが・・・

91:NAME IS NULL
06/08/15 00:15:31 .net
>90
あまり細かい事を気にすると頭髪的にチャレンジされている方々の仲間入りしちゃうぞ。

92:NAME IS NULL
06/08/17 11:00:08 .net
きみは政治的に正しいやつだね

93:NAME IS NULL
06/11/25 01:59:26 .net
てst

94:NAME IS NULL
07/03/18 01:54:18 .net
プログラム側でわかりやすいエラーを出すのはもちろんだけど
制約があればプログラムがバグってても間違ったデータは入らないので
フェールセーフにはなるよね。プログラム側の制御はフールプルーフということで。
制約の付け方が間違ってたら設計者を死刑で。


95:NAME IS NULL
07/10/27 22:41:17 .net
制約は、Not Null、主キー、一意制約くらいいしか使わない


96:NAME IS NULL
07/11/05 01:17:42 .net
>>94
自分もそう思って、可能な限り設計通りに参照整合性制約とか実装してる。
最近はマシンの性能も追いついて来た感じがあるし、設計と実装の乖離が
なくなってイイ感じ。


97:NAME IS NULL
08/06/21 22:53:28 .net
保守してみるか

98:NAME IS NULL
09/01/03 00:07:53 3emwlJX+.net
>>74
確かに実装レベルでは、Oracleが特殊だが、SQL標準からすると、Oracleが正解。
でも、Oracle8とかOracle9のせいでOracle嫌いになってしまったけどね。
(バグが多いくせにパッチ当てるのも一苦労だし)
で、制約に関しては、参照整合性制約以外は、つけたほうがいいと思う。
参照整合性だけは微妙だと思うけどね。
でも、制約にすべてのエラーチェックを任せるのはいかがなものだと思うよ。
アプリ側でチェックして、最後の砦として、制約を使うのが正解だと思う。
昔みたアプリで、とりあえず、INSERTしてみて、エラーが出たら、制約違反です
とかの処理のがあったけど、言語道断だと思う。
後、デフォルト値(制約じゃないけど)も付けといてもいいと思う。
でも、デフォルト値に設定したいがために、INSERT文で指定しないってのは
言語道断だと思う。

99:NAME IS NULL
09/04/02 10:03:38 .net
言語道断・・げんごみちだん?

100:NAME IS NULL
09/04/03 21:37:01 .net
>>99
3ヶ月掛けて考えたレスがそれか・・・

101:NAME IS NULL
09/04/24 07:29:57 .net
>>99
げんごどうだん

102:NAME IS NULL
09/07/02 12:27:22 .net
保守ついでに。
ITアーキテクトの「やってはいけない」
[データベース設計編]参照整合性制約機能を多用してはいけない
URLリンク(itpro.nikkeibp.co.jp)
はてブでは否定的なコメントが多いが、このスレの住人的にはどうなんだろ?

103:NAME IS NULL
09/07/03 18:04:26 .net
ストアドよりインデックスの方が速いよ。

104:NAME IS NULL
09/07/19 18:08:40 .net
データベースの目的によるんじゃないか
ただのストレージとしてなら、参照性合成制約なんか邪魔なだけ
モデルをあらわすものなら、制約付けとくほうがいいのかな

105:NAME IS NULL
09/07/19 22:31:04 .net
商品番号のくだり馬鹿かよ

106:NAME IS NULL
09/08/02 20:10:13 .net
>>102
「参照制約を多用してはいけない」とは思うけど、
それは主にレスポンスの問題だな
こいつの挙げてる理由はどうでもいい
・移行時に時間がかかる
→移行なんてそうそうやるもんじゃないし、別に時間かかってもいい
・マスタにないデータが登録できない
→それが正常だし、アプリで制約実装しても同じ問題が起こる

107:NAME IS NULL
09/08/02 20:47:06 .net
藤塚 勤也(ふじづか きんや)
NTTデータ 基盤システム事業本部 システム方式技術ビジネスユニット OSS技術統括 エグゼクティブITスペシャリスト(データベース)
日頃はオリジナルOSSを中心に,技術開発やそのビジネス化に従事。
特にシステムの中核であるRDBMSには常に着目し,ITスペシャリストとして後進の指導にも注力している。
「RDBMS解剖学」(翔泳社)を共著。
データの人間ってこんなレベルのやつらばかりなのか?
こんなレベルで後進の指導に注力されてもこまるんだがw

108:NAME IS NULL
09/08/02 20:53:12 .net
基本丸投げで

109:名無しさん@そうだ選挙に行こう
10/07/11 16:56:08 .net
データ社員が使えるとか何の笑い話だ?

110:NAME IS NULL
10/07/13 15:20:02 .net
> 通常業務処理の中でも問題になるケースがある。
> 例えば,1週間後に発売を予定している商品を先行して仮受注するような業務処理があった場合だ。
ふむふむ。
> まだ発売していないので商品テーブルにはその商品番号のレコードが存在しないとしよう。
ああそうですか。
>仮受注のデータも受注テーブルで管理しようとしても,商品テーブルにない商品番号のデータは追加できない。
まあそうですね。
>このような業務処理は実行できなくなってしまう。
えええ?
>仮受注のときのみ,一時的に参照整合性制約を解除するといった方法は良い設計とはいえない。
はぁぁぁ?
お前が設計してはいけない。

111:
12/05/26 14:52:17.07 .net BE:486490368-PLT(12079)
せやな

112:NAME IS NULL
14/02/27 19:09:42.31 .net
>>102
>データを移行する際、先に受注テーブルを移行させようとすると
>参照整合性違反となり、RDBMSはエラーを返す。
>必ず、商品テーブルのデータ移行後に、
>受注テーブルのデータ移行を行わなければならない。
参照元-参照先という関係は半順序だからDAG(非循環有向グラフ)で表現できる
このDAGをトポロジカルソートすれば、
参照整合性違反にならないテーブルの移行順序を機械的に導出できる
これはグラフ・アルゴリズムの初歩的な応用だ(makeコマンドを知っていれば合点がつくと思う)
>仮受注のデータも受注テーブルで管理しようとしても、
>商品テーブルにない商品番号のデータは追加できない。
>このような業務処理は実行できなくなってしまう。
これは業務分析なりDB設計のミス
もし業務ルールにおいて受注より(時系列上で)先行して受注が発生する可能性があるなら、
受注テーブルに商品番号カラムを設けてはならない
代わりに受注番号カラムと商品番号カラムを持つ受注.商品.対応テーブルを追加し、
両カラムのペアにはユニーク制約を、各カラムには参照整合性制約を設定する
この設計は、できれば業務分析時に判断してあらかじめDB設計に盛り込むのがベストであるし、
あるいは分析漏れがあったのならば(分析ミスを認めて)バグを作り込んだDBの再設計に立ち返るべき
こうした上流工程での間違いを正さずに下流工程のアプリ側で整合性検査処理を組ませるからバグが多発する
いいかえると、上流でのミスを下流の小手先で誤摩化そうとする傲慢さがプロジェクト炎上の原因になる
システム設計の基礎である初歩的なアルゴリズムの知識が無く、DB設計の基本や品質保証の定石も知らず、
これでもNTTデータ様のITスペシャリストを名乗れている(>>107)という現実に驚かされる
そして、これほど無能な自称スペシャリストに記事を書かせたITproの見識にも、疑いをいだかざるをえない

113:NAME IS NULL
14/02/28 01:03:50.30 .net
>>112の「....」の部分を訂正
誤: もし業務ルールにおいて「受注」より(時系列上で)先行して受注が発生する可能性があるなら、
正: もし業務ルールにおいて「商品(の登録)」より(時系列上で)先行して受注が発生する可能性があるなら、

114:NAME IS NULL
17/12/29 11:52:31.98 dtNZwIie.net
誰でも簡単にパソコン1台で稼げる方法など
参考までに、
⇒ 『宮本のゴウリエセレレ』 というブログで見ることができるらしいです。
グーグル検索⇒『宮本のゴウリエセレレ』
8IA9EN4TR2


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch