2009-06-09 13 views
2

私は最近、IdKeyおよびNameの列を持つテーブルTypesがあるデータベースを見てきました。SQLストアドプロシージャデザインの問題

Idはタイプのちょうど同上、Keyは、例えばタイプのショートキー名、「ビール」、およびユーザに表示することができNameたテキスト(例えば、「私たちの最大のビール」でした)。 IDはもちろんユニークで、このテーブルの主キーでした。 キーもユニークででした。他のテーブルはIdカラムを使用してテーブルタイプと常にリンクされていましたが、ストアドプロシージャは常にKeyを使用してフィルタリングしていました("X.type_Id = 3"の代わりに"X inner join Types on X.type_Id = Types.Id where Types.Key = 'beer' "など)。

私はそれを悪いアプローチと考えました。 Keyがユニークであることがわかっていても、私はではなくIdを使用します。私は、キーが変更される可能性がある(そして大丈夫です)と思うが、リンクするために別のテーブルで使用されるので、IDは変更しないでください。これをしないための規則はありますか?私たちがKey「ビール」を「ビール」に変更した場合、ストアドプロシージャの一部が正常に機能しなくなる(実際にはこのような状況がありました)。私にとっては、Idがテーブル内の行を識別した場合、必要に応じて他の属性が変更される可能性があるため、常にidを使用する必要があり、問題が発生しないようにすることは非常に直感的でした。私は正しい?

+0

同じ問題に直面していますが、これらの回答を読んだ後、私はもっと混乱しています。 – Kashif

答えて

1

主キーは1つ(単一フィールドまたは複数フィールド)で、JOINSを実行するときは常に使用する必要があります。とにかく、特定のドメイン(あなたの話をしていないドメイン)では、特定のクエリで別のフィールドを検索するのに意味があるかもしれません。あなたが言うように、これらのフィールドが変更される可能性がある場合、このクエリをハードコードするのは悪い習慣です。

+0

+1! tekBluesはアプローチの「悪い」ものを識別します。id = 3でもkey = 'beer'でも、ストアドプロシージャの値を変更することができます。 – spencer7593

5

Keyは、表内のデータにアクセスするための意味があり分かりやすい方法です。私はこのようにそれを入れてみましょう:あなたは、むしろデバッグするでしょう。この

SELECT ColumnA, ColumnB 
FROM Table T 
INNER JOIN Keys K 
ON T.KeyId = K.KeyId 
WHERE K.Key = 'Beer' 

それとも

SELECT ColumnA, ColumnB 
FROM Table T 
WHERE T.KeyId = 103461 

あなたは「103461」は何を表すか見当がつかない?

ストアドプロシージャおよびその他のパラメータ化されたクエリについても同じです。あなたはむしろ

EXEC get_items_by_category 'Beer' 

それとも

EXEC get_items_by_category 103461 

を参照してくださいか?答えは本当に明白なはずです。いい、メンテナンス可能なコードは自己文書化であり、任意のIDはそれを与えることはできません。

+2

コメントはSQLで非常に便利です... "T.KeyID = 103461 - ビール" – dotjoe

+1

しかし、キーが変わったのでスペルミスがすべてのストアドプロシージャを停止しました!人の姓を使って操作するのが良いと思いますか?スペルミスがあったために人の姓を変更するとどうなりますか?それは類似の状況です – agnieszka

+2

しかし、自然キーは時間とともに変化し、データの整合性を維持するのに非常に悪いです。私はまったく代理人に代わって自然の鍵を決して選ぶことはできませんでしたが、30年以上にわたり何百ものデータベースを扱ってきました。 – HLGEM

0

悪いデザインが好きです。基本的には悪いとは思えません。結局のところ、テーブルに複数のユニークなインデックスを持つことができます。

idがIDENTITYの代理人であることがわかりましたが、既存の値を数えることができなかったので、代わりにナチュラルキーが使用されますが、あなたが言ったように、それが存在するという保証はありませんそれは壊れる可能性がある。

しかし、その場合は、 "Beers"のすべてのidsまたはIsBeer列(およびIsFood列)を持つFlagsテーブルなど、IsBeerテーブルのように動作する可能性のある他のデザインがあります。それ。繰り返しますが、既存のものに依存することはできませんが、FKの関係があるので、少なくとも論理を破る列の変更について心配する必要はありません。さらにwelbogの例を取るために

、あなたはかなりのような構造のデータベースでアプリケーション・ロジックからの情報が含まれません。

SELECT ColumnA, ColumnB 
FROM Table T 
INNER JOIN Keys K 
    ON T.KeyId = K.KeyId 
    WHERE K.IsBeer = 1 
0

を私は一般的にあなたに同意し、darasdに反対。 ID列はサロゲートキーであると仮定します。つまり、データベース内のみであり、ユーザーには決して提示されません。私は、ほとんどのシナリオではこれを(絶対一意の識別子としての代理キーの使用)が好ましいアプローチだと考えています。現実の記述キー(例えば「蜂」)がユニークであると思われているが、現実にはそうではないと判明した状況を、よりよく扱うことができたと言います。これの古典的な例は、ユニークIDとして意図されているが実際にはそうでないことが判明したときのSSNです。

1

ID値は、変数の値を保持しているメモリアドレスであるかのように考えてください。変数名またはメモリアドレスで値を参照したいですか?

個人的には、自動インクリメントの場合は特定のIDに依存しません。特に行が削除される可能性がある場合データを一日ダンプして再度インポートすると、おそらく新しくインストールする必要があるからです。 SQLサーバーはIDを再列挙し、すべての照会が壊れます。

EDIT:(あなたのコメントに答える)

だからあなたのメインの引数は、あなたのシナリオでは、IDが変わることはありませんということで、キーは変更できますか?私はそれが悪いデザインだと言うだろう:)。あなたがそれと一緒に暮らさなければならないなら、たとえそれが非記述的であっても、IDを使うのは明らかです。 Imhoの場合、このシナリオではキーを変更することはできず、多くのクエリが中断された場合、このキーは価値がありません。

+0

大丈夫ですが、質問は頻繁に起こります - データベースをクリアしてデータをもう一度挿入するか、間違いやデータの変更( "ビール"から "ビール")のスペル? – agnieszka

+0

「ビール」の価値はどこから得ていますか?データベースに閉ループがある場合は、問題ではありません。 「ビール」を「ビール」に更新すると、ストアドプロシージャに渡す使用可能なキーのリストが変更されます。 –

+0

あなたは慎重に読んでいません。ストアドプロシージャには「ビール」がハードコードされています。「Types.Key = 'beer'」です。したがって、 "ビール"が変更された場合、ストアドプロシージャは動作しなくなります – agnieszka