これが以前に尋ねられ、答えられた場合、私を許してください。
私はPostgreSQLで実装される、在庫管理システムのスキーマの概要を説明しています。すべての製品とサービスにはSKUがあります。 ほとんど当社の製品の一部は、個別の「アイテム番号」(それがディストリビューターのカタログ番号、メーカーのモデル番号など)を持つメーカーまたはディストリビューターから来ています。しかし、それらすべてがそのような数を持っているわけではありません。社内で製造する小さなアセンブリがあり、通常、アイテム番号はありません。私たちのサービスにはアイテム番号がありません。これらの理由から、次のCREATE TABLEは私にとって意味があります。
シナリオA:
CREATE TABLE product (
sku text PRIMARY KEY,
name text UNIQUE NOT NULL, -- alternate key
price numeric NOT NULL CHECK (price > 0),
quantity numeric NOT NULL CHECK (quantity > 0),
item_number text -- hmmm...
);
ただし、これには2つの問題があります。
時々(たぶん3%から5%の時間)、item_numberは実際にはequalがSKUに与えられます。つまり、私のサプライヤの1つは、特に、製品番号の後に作成された、グローバルに一意なSKUではないと私が疑っている製品を製品に添付しています。
SKUと等しいかどうかにかかわらず、item_number(存在する場合)は、ほとんどすべての場合、私の小さな店舗のドメインで製品を一意に識別するのに十分です。
これを3NFに正規化することが心配です。 item_numberがnullになることがある場合、明らかに代替キーとして宣言できません。しかし、意味的には、私が考えることができるすべての場合において、それは存在する場所での一意の識別子です。それで、すべての属性が非素数属性item_numberに機能的に依存している上記のテーブルは、item_number item_numberが存在する場合は常に、正規化されますか?私はノーだと思っていますが、私は確かに専門家ではありません。私は次のことをすることを考えました:
シナリオB
CREATE TABLE product (
sku text PRIMARY KEY REFERENCES product_item_number (sku),
name text UNIQUE NOT NULL, -- alternate key
price numeric NOT NULL CHECK (price > 0),
quantity numeric NOT NULL CHECK (quantity > 0),
);
CREATE TABLE product_item_number (
sku text PRIMARY KEY,
item_number text
);
機能的な依存関係item_number-> price、item_number->数量などを保存することは実際には要件ではないので、シナリオBはちょっと理にかなっています。プライム以外の属性が他のプライム以外の属性を決定することはありません。
私の最後のアイデアは、item_numberが他に存在しないすべての場合に、単にskuをアイテム番号として使用することでしたが、それが良い方法かどうか疑問に思います。
シナリオC
CREATE TABLE product (
sku text PRIMARY KEY,
name text UNIQUE NOT NULL, -- alternate key
price numeric NOT NULL CHECK (price > 0),
quantity numeric NOT NULL CHECK (quantity > 0),
item_number text UNIQUE NOT NULL -- alternate key???
);
シナリオCについての私の懸念は、サプライヤーが異なるskuでカタログ番号をリサイクルする場合(たぶん?)、または2つのメーカーが両方とも「d57-red」などを作成する状況があるかもしれないということです。その場合、問題のitem_numbersにプログラムでメーカー名などのプレフィックスを付ける必要があると思います。
もちろん、私はこのすべてを考えすぎているかもしれません。
読んでくれてありがとう。 MDCCLのコメントによると、いくつかの説明があります。
属性item_number
が一意である場合、null値が含まれる可能性がある場合でも、元のテーブルに残すことができます。実際、PostgreSQL manual はこう言っています:
一意の制約上、null値は等しいとは見なされません。
したがって、これは正しい解決策になる可能性があります:
CREATE TABLE product (
sku text PRIMARY KEY,
name text UNIQUE NOT NULL,
price numeric NOT NULL CHECK (price > 0),
quantity numeric NOT NULL CHECK (quantity > 0),
item_number text UNIQUE
);
ソリューションBよりも効率的であり、ソリューションCよりもプログラミングが簡単です。
このソリューションは正規化されているため、冗長性がなく、挿入/削除の異常もありません。
追加
関係が正式にBoyce Codd正規形(第3正規形よりも厳密)になるためには、各依存関係の行列式が(スーパー)キーである必要があります。ただし、最初に、正規化理論は通常null値を処理しないことに注意してください。たとえば、Elmasri、Navatheの本「Fundamental of Database Systems」を参照。第6版、2010年:
NULL値を含む完全に満足のいくリレーショナル設計理論はまだありません
この場合、少なくとも依存関係があります。
sku → name, price, quantity, item_number
実際、sku
は関係のキーです。
次に、null値がないと仮定して、item_number
を一意にしたい場合は、別の依存関係が存在します。
item_number → sku, name, price, quantity
したがって、item_number
は別のキーです。
この関係では、他の機能的な依存関係はなく、これら2つから派生したものの一部であり、これらの依存関係はどちらもBCNFに違反していません(両方の決定要因が鍵です)。したがって、関係はボイス・コッドの正規形になります。
一方、item_number
にnull値が含まれる可能性があると考える場合、2番目の依存関係が保持されていないと見なすことができるため、リレーションシップは再びBCNFにあります。