制約っていらなくね?

このエントリーをはてなブックマークに追加
1NAME IS NULL
プログラム側で制御しろよ
2NAME IS NULL:04/06/17 23:52 ID:dpurb/Z2
Uze
3NAME IS NULL:04/06/17 23:56 ID:xzoV3ZXe
そう思うときもあるけど、それがあるお陰で、
データの整合性が取れてるって面もあると思う。

んが、そのデータの整合が取れてるっていうのが、目に見えて
実感できないから、「制約ってめんどいな」とは、正直思う。
4NAME IS NULL:04/06/18 00:31 ID:???
糞っスレ
5NAME IS NULL:04/06/18 13:40 ID:Zpejz88K
>>1 は無知。
6NAME IS NULL:04/06/18 14:11 ID:???
>>1を制約しろ
7NAME IS NULL:04/06/18 19:43 ID:???
>>1
DB側で制御できたら、プログラム側で制御しなくて良いのだが。
8NAME IS NULL:04/06/18 20:15 ID:???
ついでにストアドもイラネ
9NAME IS NULL:04/06/18 22:23 ID:Zpejz88K
>>8 はいはい。
おのれは、いずれホームレス^^
10NAME IS NULL:04/06/18 22:36 ID:???
>>8はMySQLユーザー
11NAME IS NULL:04/06/19 07:38 ID:OHujBfWT
ただDBサーバーにアプリケーション機能を盛り込み過ぎるのもどぉーかなー
12NAME IS NULL:04/06/19 10:10 ID:iDH3OAyt
>>11
その方が効率的だから、そうするのだろうが。
dbをISAM(索引順編成ファイル)としか使ってないの?w
13NAME IS NULL:04/06/19 16:32 ID:???
制約いらないよね。 いらないから使わなければいいだけのこと。
制約にひっかかるデータは事前にチェックして、どの部分がまずいのかを
使う側に明確に表示させたいからね。
そのままエラー内容表示させるのもダサいしね。
14NAME IS NULL:04/06/19 18:26 ID:???
>>13
同意。
そもそも、制約に引っかかるようなデータを書き込むアプリは、作りがアレだとおもうが
15NAME IS NULL:04/06/19 19:06 ID:???
>>13-14
ユニーク制約が、アプリ側でチェックできるんでつね?
重複チェックとは、別次元の問題だと思いまつが。。。
16NAME IS NULL:04/06/19 20:25 ID:???
>>13
>使う側に明確に表示させたいからね。
>そのままエラー内容表示させるのもダサいしね。
制約違反はアプリにコールバックされるだろ
そこからエラーメッセージ出せばいいだけじゃん・・・
17NAME IS NULL:04/06/19 22:40 ID:rF590MRN
>>16
そうだよね〜
あるマスタにないものを別のテーブルに入れてはいけない場合を考えてみよう
プログラムがそれをやるとなると
マスタの中に存在するか調べてから入れないといけなくなる
制約使えばエラーが発生するのでそこでメッセージ受け取って
適切なエラーメッセージクライアントに返すだけ

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

でも、エラー処理をまかせるってのは、どうなんだろ。
いまどきは、そういうもんなの?
20NAME IS NULL:04/06/20 00:39 ID:???
>>19
>エラー処理を任せる

ここで言ってるエラー処理って
DBからエラー受け取って
エラーメッセージを振り分けて表示するだけのことじゃないかな?
実際、制約あればエラーあった時点でDB更新は無いわけだし
プログラミングは楽になる
21NAME IS NULL:04/06/20 01:19 ID:???
 本来データの重複や規定外の値が入るのを防ぐのは内部スキーマの担当で、それを
外部スキーマにやらせるならば、作成するすべての外部スキーマが
エラーチェック->●エラーなら=>エラー表示してやり直し ●OKなら=>保存=>次行ってみよー
という機構をもつ必要がある。そうすると外部スキーマの処理数が増えてバグを作りこむ
可能性も上がり、万一ひとつでもエラーチェックが甘い外部スキーマがあればそれのために
内部スキーマに整合性エラーが出かねない。
 その点内部スキーマに持たせれば、外部スキーマは
保存->●エラーなら=>エラー表示してやり直し ●OKなら=>次行ってみよー
と、エラーチェックの結果を判断するだけでよくなって万一バグがあってもランタイムエラーで済む。
 アプリの作成中は良くても、今後増改築があったときにすべてのテーブルに対してどのような
データを入れてはいけないか、忘れてしまってひとつでもエラーチェックの甘いアプリを
作ったら後が悲惨そう。

 大体、もらったデータは例え候補キーが重複してたりNULLを含んでいても関係なく保存
していくDBMSって、「そこのコンビニ袋の中身冷蔵庫に入れといてくれよ」って言ったら
「うあぁぁ、カップラーメンも牛乳もガツンとみかんもみんな冷蔵庫に入れてあるうぅゥゥー!!!」
てなことするタコスケっぽくて情けなくない?
22NAME IS NULL:04/06/20 01:40 ID:???
>>21

俺もなるべくならDBにやらせたい派だな
だってNullはDBの機能で入れられないようにするくせに
外部キー制約はプログラミングで実装ていうのはおかしいよな

ただ、ひとつだけ
もし、「あ、このデータ消したいな」と思った場合に困るんだよな
そうした場合には制約ないほうがいいし
事実そうしているプロジェクトが多い
23NAME IS NULL:04/06/20 01:56 ID:???
>22
つ[ ON DELETE CASCADE ]
つ[ ON DELETE SET NULL ]
24NAME IS NULL:04/06/20 07:02 ID:???
今年のTE(DB)の試験では制約がいっぱい出ました
25NAME IS NULL:04/06/29 02:09 ID:Pxx6PBqy
まあ、論理設計の意図を反映させる意味で制約はつけてるけど。
正直、ユニーク制約なんかはユニークインデックス付ける方がよくやる。
26NAME IS NULL:04/07/08 13:48 ID:???
NOT NULLは大嫌い。
何度ユーザーに裏切られた事か。
業界標準コードがNULLの商品データとか
本番稼動後になってから平気で寄越したり。

そもそも画面から更新処理を行おうとした時点で
DB叩く前に入力チェックしなきゃいけないし。
未入力のフィールドにフォーカスあてたり
フィールドごとにエラー文言変えたり。

データはなるべく静的な物として捉えたいので
業務ロジックを盛り込む事は避けたいです。

ただ、ユニークや外部キーなどは
どちらかというとシステム寄りの要件なので
場合によってはつけた方がいいかなあとも
最近は思い直してます。
27NAME IS NULL:04/07/08 22:36 ID:???
まぁシステムによりけりだね。
制約は断じて「業務ロジック」では無い。
でも設計がアレなシステムでは、制約が業務ロジック化してしまう。
2826:04/07/09 10:17 ID:???
制約自体に罪はない、設計がアレなだけだ、って事ですね。
今まで誤解してたよ、ごめんよ、制約。

全てアプリ側でコントロールすると
>21みたいな事にもなるしね。
これからは心を入れ替えて制約も活用してみます。

皆さん具体的にどうですか?
制約使って便利だーいやトラブったーとかあります?
外部キーとかってどうしても使う勇気が湧かないんですよ。
ただ新しい事やりたくないってだけなんですが。
29NAME IS NULL:04/07/10 18:41 ID:+BBjcTFg
単に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 レコードを削除したいのです。
なんかいい方法ありますか?
30NAME IS NULL:04/07/10 19:04 ID:???
大変つっても一回書きゃおしまいだろ?
31NAME IS NULL:04/07/10 19:09 ID:???
>>30
処理にかかるコストの問題です。
32NAME IS NULL:04/07/10 21:46 ID:???
>>29
TABLE_A.IDに ON DELETE NO ACCTION 付けて全行削除してみればいいんじゃないの?
33NAME IS NULL:04/07/10 21:55 ID:???
コストの問題なら、>>29でどのくらい問題なのか書かんと。
3429:04/07/10 22:20 ID:???
>>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 が指定されてると、削除しちゃいけない行を削除したときにはエラーになって処理してもらえないと思いますが、
ちょっと勘違いしてますかね?

3529:04/07/10 22:59 ID:???
自己レスです。ちょっと思いついちゃいました。

テーブル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);

みたいな感じですかね。
シンプルで速そうな気がしますが、いかがでしょう?

でも、外部キーに参照されてるレコードなのか否かの判定方法は知りたいので、知ってる人がいましたらよろしくです。
3629:04/07/10 23:18 ID:???
たびたびすみません・・・

>>35 のやり方だと、TABLE_FK の外部キー制約は TABLE_B や TABLE_C に継承されないっぽいです。
TABLE_B、TABLE_C それぞれで外部キー制約を付ける必要があるようです。
ハマるところだった・・・
危ない危ない。
>ばっさり DELETE してしまってもいいですが、WHERE には結局数十個のテーブルについての EXIST が並ぶことになり、
>パフォーマンスは悪そうです。

数十個といっても加算的なものだし。
逆にテーブルが3個しかないなら期待するパフォーマンスが出る
という保証はないから、まずは計測してみれ。

>>34を読む限りでは、テーブル3個の場合のパフォーマンスにも
満足できなそうに思えるんだが。

>DBの内部では、外部キーに参照されたレコードが削除されるときに、そのことを瞬時に把握する仕組みを持っているはずで、

ふつう、そんなものはない。
ON DELETE CASCADEも結局、トリガで対象のテーブルから
deleteしてまわっているのと違いはない。
3829:04/07/11 10:23 ID:???
>>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 のバグですかね?
>>38
TABLE_B.IDとかには当然indexを設定していると思っていたんだが。

>INDEX 付ければ速くなるでしょうが、ログテーブルを逆引きするためにいちいち INDEX の領域とるのはなぁ、

本当にdeleteのパフォーマンスが問題ならindexを作る。パフォーマンスを
犠牲にしてでも領域を節約する必要があるなら作らない。
ディスク領域を気にしているようだが、じゃあこれらのテーブルにどのくらいの
レコードが登録されてどれくらい領域を必要とするか見積もってる?
チューニングの話なら「遅そう」「領域食いそう」とかの感覚的な話じゃ
先に進まないよ。そのへん見積もれないうちから小手先のテクニックを
弄しても無駄に終わる可能性が高いから、まずは正攻法でやってみれ。

>ということは、TABLE_A が削除されるときに、外部キー参照しているテーブルをいちいち検索しに行ってるわけでは
>ないのかな、と思ったのですが、いかがでしょう?

FKとB、Cは別のテーブルであって、FKをselectした際にデフォルトで
BとCも一緒に検索してるだけ。Aにない値がFKに入ったわけではない。

>しかし、継承させたテーブルで継承元の制約が受け継がれないってのは、一般的な仕様なのでしょうか。
>それとも PostgreSQL のバグですかね?

「一般的な仕様」などはない。それはバグじゃなくてPostgresの仕様。
たしかに、継承するなら制約やトリガなども継承された方が便利だと
思うんだけどね。
>>29
もう少し手短にまとめてくれ。読むのがめんどくさい。

一般的に速度と記憶域はトレードオフ。実際に手を動かさずに、いつまでも机上の
空論を弄んで、根拠のない妄想に見切りつけずにあれこれ悩むのは時間の無駄。
そもそも更新速度の低下でならまだしも、記憶域を圧迫する理由でインデックスを
張るのを躊躇するような貧相な環境なら、まず環境を見直すべき。
4129:04/07/12 02:30 ID:???
>>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 を張らないと
ダメなんですね?
うーん、めんどくさいなぁ・・・
そう思うと、テーブルを継承するメリットってなんなんでしょうかね?
42NAME IS NULL:04/07/21 01:04 ID:???
制約やデフォルト値を細かく指定しておくと
ドキュメントがないとか,前任者が遁走した時の場合でも
ある程度何をしたかったかがわかるのでよい
43NAME IS NULL:04/07/21 10:57 ID:???
>>42
うんうん、わかるわかる(泣)。
俺、火消し役ばっかりやらされてるんで。

でも、遁走するような奴の設計には
懐疑的になってしまうのもまた事実ですね。

でも何も無いよりいいか。
44NAME IS NULL:04/07/21 11:11 ID:???
適当な設計やっても平気で提案できるくらいの奴は、
神経が図太い場合が多いから、逆に辞めない。
間違った仕様を正したいのに、認められなくて
耐えられなくなって辞める奴の方が多い。
憎まれっ子世にはばかる。
45NAME IS NULL:04/07/21 11:12 ID:???
関係ないけど、火消しを入れる予算があるのなら、
最初から出火させない人を雇えよと思ったりもする。
火消し担当の人が、最初からプロジェクトに関わればいいのに。
46NAME IS NULL:04/07/21 11:22 ID:???
>>45
自然発火とか
47NAME IS NULL:04/07/21 16:48 ID:???
>>45
そういった事が出来れば火消しなんか使わないかと。
むしろ火消しが出来る人(又はグループ)を
予備選力としてヤバい所に投入ってのは防御の基本かと。
(史実の重戦車大隊みたいだな)
4843:04/07/21 18:53 ID:???
>>45
あたくしの場合、火消し役やらされてる間も
他の案件の保守で人月工数出とるんで
コストかかっとらんのですわ。

だから便利に使われるって訳です。疲れた・・・・。
49NAME IS NULL:04/07/21 19:32 ID:???
納期間に合わなさそう

新しい人材を大量投入

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

さらに炎上


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

頑張ってアプリ側で実装ですよ。
52NAME IS NULL:04/12/15 07:00:38 ID:6kA6XGLm
このスレっていらなくね?
53NAME IS NULL:04/12/15 23:47:32 ID:???
あとから設計見てどういう意図で組んだのかわかりやすいから制約は付けてるなあ
どーせ突っ込む前にデータチェックするんだけどね
54NAME IS NULL:05/01/04 23:49:35 ID:gtuR+WFj
制約かぁ・・・

参照性合成制約とかトリガーによるチェックはどうかと思うが、
主キーとNOT NULL制約は最低限付けた方が良いな。
55NAME IS NULL:2005/03/29(火) 17:51:13 ID:???
1 WEBからデータ入力(クライアントでのデータチェック)
2 サーバプログラムで加工(サーバでのデータチェック)
3 DBに格納(DBMSでのデータチェック)

なんかもどかしい.
56NAME IS NULL:2005/07/27(水) 11:06:36 ID:rghdAW4Q
保守する時に、
参照整合性制約サイコー。
トリガーは糞。

と思う事が多いのだが、
どうか?
57NAME IS NULL:2005/07/27(水) 13:59:40 ID:???
>>56
参照整合制約って使った事ないけど
保守する上でどうサイコー?
本で読むような利点じゃなくて
現場の濃い話希望。
58NAME IS NULL:2005/07/28(木) 10:46:45 ID:KXoQY93/
売春婦(DB)とその客(アプリ)に例えれば・・・。
入れるときに相手にゴムの着用を求めても、それが万全とはいえないし、そもそもつけるかも強制できない。
そうであれば、自分で制約(避妊手段)を準備しておくのが、変なデータを作らないための予防策。
59NAME IS NULL:2005/07/28(木) 18:55:51 ID:???
>>57
56じゃないが俺はゴミが入らないのが利点だと思う。
これ以上でもこれ以下でもない。
ありえないデータが入ってるDBなんざみたくねぇ!!

トリガーは便利だと思うけどな。
そのありえないデータを削除したりするのによく使う。
60NAME IS NULL:2005/07/28(木) 23:56:28 ID:???
トリガーって、ER図から読み取れないから怖いやね。
時刻更新とか、極簡単で引継ぎしやすい物であれば便利だと思う。

スパープログラマな人が、作ったオレサマトリガーは、簡便∩( ・ω・)∩
61NAME IS NULL:2005/07/29(金) 00:17:42 ID:???
参照整合性制約を張るとインデックスが張られるやね。
そのER図をプログラマに配っておけば、自然とコチラの意図通りの
インデックスを使ったSQLを書いてくれるといいなぁ。。。
(そこそこのレベルの人なら分かってくれる。)

他には、
・参照整合性制約に基づいた連鎖更新・削除が便利。

・Access2003のXMLエクスポート機能を使う場合に
 参照整合性制約に基づいて親子テーブルを
 エクスポート出来るとか。

中小規模で、レスポンス性能とかシビアでなければ
参照整合性制約付けといた方が管理しやすいと思う。

問題になれば、外すだけで性能アップさせましたと
言えるかもしれないし。。( ̄ー ̄)ニヤリ
62NAME IS NULL:2005/07/29(金) 00:18:49 ID:???
現場の濃い話って、↓こんなのか?

中小SI ヘッポコシステム
客「このデータ消したいなぁ」
担「何度も申し上げた通り(略」
客「前の担当者なら(略」
上司「ヤレ!」
担「しかしDBを直接弄るのは、(略」
上司「この辺のデータを(略」
担「...」
客「データがオカシイゾ(略」
上司「誰がそんな事をヤレと(略」
担「...」
63NAME IS NULL:2005/07/29(金) 12:22:38 ID:???
>>59
ゴミの排除を制約に全部まかせちゃうんですか?
恐いなーと思って。

何がゴミかとかありえないデータかってのは
業務要件だったりする事が多いわけで
それはアプリ側で実装されてた方がわかり易いし
管理も楽だと思うんですよ。

で、制約をつけると、再実装になるし
保守も難儀な事になりそう。

そうでもないのかな?
6463:2005/07/29(金) 12:27:28 ID:???
あ、煽ってる訳じゃないです。
制約に対する偏見なのかなあって
ちょっと思ってきては居るんで
背中押してもらいたいというのが本音。

>61の連鎖削除・更新も
業務要件だからアプリで実装したいんですよねぇ。
トリガーもそうなんですが。

ださいのかなー。

あっ、でもレスポンス向上の一手に使えるってのは
いいっすね!そういうかわいい悪どさは好きです。
65NAME IS NULL:2005/07/29(金) 13:13:32 ID:ug+wSNY+
>>63-64
直接引用じゃなく、要点絞って記述するね。

>アプリで実装するほうが判りやすくて楽
1つのテーブルに対する処理が10個も20個もあるアプリで、
全ての処理が正しく動作することを補償するのは楽でしょうか?
NOT NULLの制約もないDBとか最悪ですよ。

>制約をつけると再実装
逆です、制約がまず実装でアプリ側が再実装。
アプリ作るのに、DB設計もせずに始めるのでしょうか?

で、トリガーと制約は別問題。
論理的制約をトリガーで実装するってのはあるけど。

主キーもない、NULL制約もないDBなんて、DB使わないでファイルに書けばいいじゃん。w
66NAME IS NULL:2005/07/29(金) 13:48:36 ID:ZZgow+OE
火と大杉で見れないよ
6763:2005/07/29(金) 14:08:49 ID:???
>>65
まず具体的にNOT NULL制約に話なんですが、
業務要件としてNOT NULLなものって
アプリ側で入力チェックしますよね。
アプリ側の実装はどうしても必要になっちゃう。
で、そういうチェックはユーティリティクラスとかヴァリデーターとか
そんな風に共通化する訳です。

1つのテーブルに対して10個も20個も処理があったとして
アプリ側の設計で実装は1つにまとめられると思います。

で、ままあるんですが、当初NOT NULLだと思ってたのが
実はNULLもあるんだよーなんて突然お客様に言われた時に
アプリ側で仕様が把握し切れればいいんじゃないかなと思っちゃう。

>アプリ作るのに、DB設計もせずに始めるのでしょうか?
DB設計は事前にしますよ。ER図も書きます。
でもそれは論理設計と言うか概念設計です。
実際にDBを構える時はまた考え直します。

概念設計において業務要件を反映した制約を
そのまま実装としてDBに入れるか、
アプリでやるかって所だと。

ちょっと話はずれますが、
概念設計と実装で構成が違うのは当たり前にやってます。
特に識別子の考え方。概念では識別子は業務に沿って考えます。
だから「注文番号 + 行番」なんて複合キーもガンガン使います。
でも実装では、「注文明細ID」をキーにします。
勿論、一意制約とインデックスは「注文番号 + 行番」につけますけど。

だから、参照整合やNOT NULLに関しても
実装ではぶいてアプリで実装ってのにあまり抵抗がないのかも
知れません。

うーん、書いてて自分の強い優位性が見出せぬ。
過去の振り返りにしかなってない・・・わはは。

レス有難う御座います。長文失敬でした。
68NAME IS NULL:2005/07/29(金) 14:33:29 ID:ug+wSNY+
>>67
> 業務要件としてNOT NULLなものって
> アプリ側で入力チェックしますよね。
> アプリ側の実装はどうしても必要になっちゃう。
> で、そういうチェックはユーティリティクラスとかヴァリデーターとか
> そんな風に共通化する訳です。

アプリでの入力チェックとNotNull制約では、後者のほうが広い意味です。
入力チェックしても防げないバグデータでも制約で防げます。
それに、アプリを通さないDBテーブル同士でのデータ登録とか更新もありますし。

> 1つのテーブルに対して10個も20個も処理があったとして
> アプリ側の設計で実装は1つにまとめられると思います。

クラスなど実装が1つにまとめられることと、SQLの種類が複数になることは別問題ですよ。
その各パターン毎の更新などに対して、不慮の事故などをどのようの防ぐのですか?
全てのパターンを1つの汎用SQLで行った場合にしても、それらのパターン毎の試験は必要です。

> 概念設計において業務要件を反映した制約を
> そのまま実装としてDBに入れるか、
> アプリでやるかって所だと。

DBの責務としての制約はDBでやるべきだし、アプリの制約はアプリでやるべき。
それに、DBが常にアプリを通して更新されるとは限らないし。
メンテとか、後の修正や他システムとの連携などで、そのアプリに対する制約を相手に望めますか?

> うーん、書いてて自分の強い優位性が見出せぬ。
> 過去の振り返りにしかなってない・・・わはは。

だって、便利な機能を否定して茨の道を歩んでるから。
両方制約すればいいんですよ、DBとアプリの独立性を高めて考えて、それぞれの責務を課す。
DBは自分の入れられたくないデータを制約し、アプリは他に出せないデータは出さない。
6963:2005/07/29(金) 15:35:16 ID:???
>>68
うーむ、茨の道、耳が痛いです。
やっぱりやった事ないから恐いってだけなんでしょうかね。
有難う御座います。

確かに、アプリを経由しないデータ連携などではお手上げですね。
最初からそんな要件なければいいですが
案件ごとに制約の実装方法がDB or アプリで
バラバラになっちゃうのも気持ち悪いですし
ポリシーとして最初から統一しちゃう方が、確かに安心。

あと、DBからの制約のエラーと
アプリでのエラーメッセージのマッピングで
困った事とかないですか?
DBからのエラーコードじゃ判りきらんよ、とか。
それも気になる所なのです。

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

そもそもとして、DBに制約をつけるのってそんなに大変か?w
Check制約にしても、そんなに手間じゃないでしょ。
7163:2005/07/29(金) 16:07:46 ID:???
おっしゃる通り、別に大変でもないですよね。わはは。

飛ぶのが恐いわけじゃない、落ちていくのが恐いんだ
by 寺山修司

って心境です。
派手にバグを出してデータパッチわんさか当てなきゃーとか
なった時に、参照整合とかで苦労しないかなーとか
勝手に妄想してるのです。

次は飛んでみるかな。
72NAME IS NULL:2005/07/29(金) 16:21:06 ID:6uLcICyZ
>>71
想定してる場面が発生する原因は・・・。
1)システム分析が甘く、DB設計が間違っている為、実情に合わない制約をDBに課した
2)そもそもの業務がフレキシブル(w、なので、その時点での制約が邪魔になる。
のどちらかだと思うが。

前者であれば技量を磨くしかないし、後者はそもそも制約を付与する設計がやっぱり間違っているともいえる。
制約って基本的にはきつく課しておいて、緩めるときに本当に緩める理由があるか考えるほうが安全だよ。
73NAME IS NULL:2005/07/29(金) 23:47:30 ID:???
>>64
連鎖削除・更新は、注文-注文明細とかで考えると、
業務要件では無くRDB側の物理実装時の都合だと思う。

と、言いつつも管理が面倒なので、アプリ側に実装させて
自分がDBを直接弄る場合にのみ、一時的に有効にするのが
オレサマのやり方だな。
74NAME IS NULL:2005/07/29(金) 23:56:57 ID:???
NOT NULLの制約については、文字型について
Oracleと、SQLServerで扱いが微妙に違うのがイタイな。
Oracleは、NullとEmptyの違いが無いのに対して
SQLServerは、NullとEmptyを明確に区別する。

そのため、ほとんどのフィールドは、Nullを許可しているな。

考え方は、SQLServerの方が好きだな。
他の、DBってどうなのだろう。。?
75NAME IS NULL:2005/07/30(土) 00:17:52 ID:???
さんざん書かれているけど、基本的な考えとしてアプリケーションありきの
モデリングを行うのは、後々の拡張性とか考えると嫌だな。

↓ちょうど良い記事を見つけた。
データは安定している 〜POAからDOAへ
ttp://pcweb.mycom.co.jp/series/stratesys/010/

所で、
制約の管理とか、モデリングツールにより
かなり効率が違ってくると思うのですが、
何かつかってます?

漏れの場合は、Erwin3.5使ってて
最近は値段の関係から、ER/Studioに移行させられそう。。。
76NAME IS NULL:2005/07/30(土) 00:31:04 ID:???
うちはOBERです。
そーんなに使い勝手いいとは思えないかな・・・。
77NAME IS NULL:2005/07/30(土) 06:07:29 ID:???
チラシの裏最強!
78NAME IS NULL:2005/07/30(土) 09:53:03 ID:???
>>77
どの辺がチラシと思った?
79NAME IS NULL:2005/07/30(土) 22:52:42 ID:???
>>74
DB2もPostgreも区別するよ。
つーかOracleが特殊なだけな気がする。
80NAME IS NULL:2005/07/31(日) 02:33:05 ID:???
>>78
日記の裏でなくて
モデリングツールなぞ
チラシの裏で十分です
って話でそ。
81NAME IS NULL:2005/07/31(日) 03:00:10 ID:???
>>80
そういう意味か。。

制約の保守が〜、といった話が出ていたので、
その流れのつもりだったんだけどな。

漏れは、Erwin様にDDLだとか、管理してもらっているので、
モデリングツール無くなると、作業効率がた落ちなんだな。
DB自体と物理モデルの完全比較とか、使いこなすまでが
大変だけ使いこなすとスコブル便利だよ。

もう、手動で管理する自信ありませんぜ。
82NAME IS NULL:2005/07/31(日) 03:03:30 ID:???
>>79
なるほどね。
サンクス!
83NAME IS NULL:2005/08/01(月) 05:30:05 ID:???
>>81
モデリングツールは設計ツールじゃなくて保守ツールと考えると納得いく。
設計は紙と鉛筆が基本だけど、後のことを考えてあえて手間ひまかけてツールを使う。
だから保守をやらない開発メンバーには評判が悪かったりする。
84NAME IS NULL:2005/08/01(月) 10:31:03 ID:???
そうなのか、評判悪いのか。。

漏れは中小規模な案件が多いせいか、
引き継ぎと言う事例が少ないだけで(~-~;
しょうがなしに保守や改善対応している
開発よりのタイプなんだけどな。

そういえば、UMLっぽい物をVisioで
書こうとした時はメンドクセと思った。
あんな感じなのかな。
85NAME IS NULL:2005/08/01(月) 10:48:40 ID:???
「保守を行わない開発メンバー」という
箇所を見落としてた。

とはいえ、統一したフォーマットの
DDL書いてくれるだけでも便利だと
思うのだけどな。

そういった観点か既に保守する立場と(略
86NAME IS NULL:2005/08/01(月) 12:08:59 ID:???
チラシの裏書いた本人だが、終盤はモデルツールでやりますよ。
ただ、概念から順次ツールに合わせて落としていくっていうのがどうも制限になって嫌で。
手法の1つとしてはツールの手順でもいいけど、設計ってそこまで理想的に出来ないこと多いし。
とりあえずの概念設計とかはチラシの裏というか裏紙が一番いい。
87NAME IS NULL:2005/08/01(月) 22:58:35 ID:???
そのままの意味だったとは。。。
そいつぁ 盲点だたよ (^ ^ ;
88NAME IS NULL:2006/06/08(木) 23:51:07 ID:???
ここで書き込んでいる人たちはずいぶん専門的な話題が多いようですが、
具体的にいったいどんな規模のどんなシステムに関わってるんでしょうか??

ここでいう「中小」とはどれくらいのものを指すんだろう・・・。
89NAME IS NULL:2006/06/30(金) 00:59:24 ID:???
中…1000万行程度、数十テーブル程度で同時接続ユーザ数100人程度
小…100万行程度、数テーブル以下で列数最大20-100列、同時接続ユーザ数数名程度
90NAME IS NULL:2006/08/05(土) 00:40:54 ID:???
今やってるのは
100万行程度、数百テーブルで列数最大100列、同時接続ユーザ数数名程度
ですが・・・
91NAME IS NULL:2006/08/15(火) 00:15:31 ID:???
>90
あまり細かい事を気にすると頭髪的にチャレンジされている方々の仲間入りしちゃうぞ。
92NAME IS NULL:2006/08/17(木) 11:00:08 ID:???
きみは政治的に正しいやつだね
93NAME IS NULL:2006/11/25(土) 01:59:26 ID:???
てst
94NAME IS NULL:2007/03/18(日) 01:54:18 ID:???
プログラム側でわかりやすいエラーを出すのはもちろんだけど
制約があればプログラムがバグってても間違ったデータは入らないので
フェールセーフにはなるよね。プログラム側の制御はフールプルーフということで。
制約の付け方が間違ってたら設計者を死刑で。
95NAME IS NULL:2007/10/27(土) 22:41:17 ID:???
制約は、Not Null、主キー、一意制約くらいいしか使わない
96NAME IS NULL:2007/11/05(月) 01:17:42 ID:???
>>94
自分もそう思って、可能な限り設計通りに参照整合性制約とか実装してる。
最近はマシンの性能も追いついて来た感じがあるし、設計と実装の乖離が
なくなってイイ感じ。
97NAME IS NULL:2008/06/21(土) 22:53:28 ID:???
保守してみるか
98NAME IS NULL:2009/01/03(土) 00:07:53 ID:3emwlJX+
>>74
確かに実装レベルでは、Oracleが特殊だが、SQL標準からすると、Oracleが正解。
でも、Oracle8とかOracle9のせいでOracle嫌いになってしまったけどね。
(バグが多いくせにパッチ当てるのも一苦労だし)

で、制約に関しては、参照整合性制約以外は、つけたほうがいいと思う。
参照整合性だけは微妙だと思うけどね。
でも、制約にすべてのエラーチェックを任せるのはいかがなものだと思うよ。
アプリ側でチェックして、最後の砦として、制約を使うのが正解だと思う。
昔みたアプリで、とりあえず、INSERTしてみて、エラーが出たら、制約違反です
とかの処理のがあったけど、言語道断だと思う。
後、デフォルト値(制約じゃないけど)も付けといてもいいと思う。
でも、デフォルト値に設定したいがために、INSERT文で指定しないってのは
言語道断だと思う。
99NAME IS NULL:2009/04/02(木) 10:03:38 ID:???
言語道断・・げんごみちだん?
100NAME IS NULL:2009/04/03(金) 21:37:01 ID:???
>>99
3ヶ月掛けて考えたレスがそれか・・・
101NAME IS NULL:2009/04/24(金) 07:29:57 ID:???
>>99
げんごどうだん
102NAME IS NULL:2009/07/02(木) 12:27:22 ID:???
保守ついでに。

ITアーキテクトの「やってはいけない」
[データベース設計編]参照整合性制約機能を多用してはいけない
http://itpro.nikkeibp.co.jp/article/COLUMN/20090512/329851/

はてブでは否定的なコメントが多いが、このスレの住人的にはどうなんだろ?
103NAME IS NULL:2009/07/03(金) 18:04:26 ID:???
ストアドよりインデックスの方が速いよ。
104NAME IS NULL:2009/07/19(日) 18:08:40 ID:???
データベースの目的によるんじゃないか

ただのストレージとしてなら、参照性合成制約なんか邪魔なだけ
モデルをあらわすものなら、制約付けとくほうがいいのかな
105NAME IS NULL:2009/07/19(日) 22:31:04 ID:???
商品番号のくだり馬鹿かよ
106NAME IS NULL:2009/08/02(日) 20:10:13 ID:???
>>102
「参照制約を多用してはいけない」とは思うけど、
それは主にレスポンスの問題だな

こいつの挙げてる理由はどうでもいい
・移行時に時間がかかる
→移行なんてそうそうやるもんじゃないし、別に時間かかってもいい
・マスタにないデータが登録できない
→それが正常だし、アプリで制約実装しても同じ問題が起こる
107NAME IS NULL:2009/08/02(日) 20:47:06 ID:???
藤塚 勤也(ふじづか きんや)
NTTデータ 基盤システム事業本部 システム方式技術ビジネスユニット OSS技術統括 エグゼクティブITスペシャリスト(データベース)
日頃はオリジナルOSSを中心に,技術開発やそのビジネス化に従事。
特にシステムの中核であるRDBMSには常に着目し,ITスペシャリストとして後進の指導にも注力している。
「RDBMS解剖学」(翔泳社)を共著。

データの人間ってこんなレベルのやつらばかりなのか?
こんなレベルで後進の指導に注力されてもこまるんだがw
108NAME IS NULL:2009/08/02(日) 20:53:12 ID:???
基本丸投げで
109名無しさん@そうだ選挙に行こう:2010/07/11(日) 16:56:08 ID:???
データ社員が使えるとか何の笑い話だ?
110NAME IS NULL:2010/07/13(火) 15:20:02 ID:???
> 通常業務処理の中でも問題になるケースがある。
> 例えば,1週間後に発売を予定している商品を先行して仮受注するような業務処理があった場合だ。
ふむふむ。
> まだ発売していないので商品テーブルにはその商品番号のレコードが存在しないとしよう。
ああそうですか。
>仮受注のデータも受注テーブルで管理しようとしても,商品テーブルにない商品番号のデータは追加できない。
まあそうですね。
>このような業務処理は実行できなくなってしまう。
えええ?
>仮受注のときのみ,一時的に参照整合性制約を解除するといった方法は良い設計とはいえない。
はぁぁぁ?

お前が設計してはいけない。
111 【30.7m】 電脳プリオン:2012/05/26(土) 14:52:17.07 ID:??? BE:486490368-PLT(12079)
せやな
112NAME IS NULL:2014/02/27(木) 19:09:42.31 ID:???
>>102
>データを移行する際、先に受注テーブルを移行させようとすると
>参照整合性違反となり、RDBMSはエラーを返す。
>必ず、商品テーブルのデータ移行後に、
>受注テーブルのデータ移行を行わなければならない。

参照元-参照先という関係は半順序だからDAG(非循環有向グラフ)で表現できる
このDAGをトポロジカルソートすれば、
参照整合性違反にならないテーブルの移行順序を機械的に導出できる
これはグラフ・アルゴリズムの初歩的な応用だ(makeコマンドを知っていれば合点がつくと思う)

>仮受注のデータも受注テーブルで管理しようとしても、
>商品テーブルにない商品番号のデータは追加できない。
>このような業務処理は実行できなくなってしまう。

これは業務分析なりDB設計のミス
もし業務ルールにおいて受注より(時系列上で)先行して受注が発生する可能性があるなら、
受注テーブルに商品番号カラムを設けてはならない
代わりに受注番号カラムと商品番号カラムを持つ受注.商品.対応テーブルを追加し、
両カラムのペアにはユニーク制約を、各カラムには参照整合性制約を設定する

この設計は、できれば業務分析時に判断してあらかじめDB設計に盛り込むのがベストであるし、
あるいは分析漏れがあったのならば(分析ミスを認めて)バグを作り込んだDBの再設計に立ち返るべき
こうした上流工程での間違いを正さずに下流工程のアプリ側で整合性検査処理を組ませるからバグが多発する
いいかえると、上流でのミスを下流の小手先で誤摩化そうとする傲慢さがプロジェクト炎上の原因になる

システム設計の基礎である初歩的なアルゴリズムの知識が無く、DB設計の基本や品質保証の定石も知らず、
これでもNTTデータ様のITスペシャリストを名乗れている(>>107)という現実に驚かされる
そして、これほど無能な自称スペシャリストに記事を書かせたITproの見識にも、疑いをいだかざるをえない
113NAME IS NULL
>>112の「....」の部分を訂正
誤: もし業務ルールにおいて「受注」より(時系列上で)先行して受注が発生する可能性があるなら、
正: もし業務ルールにおいて「商品(の登録)」より(時系列上で)先行して受注が発生する可能性があるなら、