2016-12-19 5 views
4

私はMySQL DBに3つのテーブルを持っています。 これは、組織関連のものがあるメインテーブルです。すべての組織には、一意の識別子があります。これは、一部の表の外部キーです。外部キーの可能な値をどのように区切ることができますか?

org 
+------------+-------------+ 
| org_id  | name  | 
+------------+-------------+ 
| 1   | a   | 
| 2   | b   | 
| 3   | c   | 
+------------+-------------+ 

これはグループテーブルです。組織は多くのグループを持つことができます。

groups 
FOREIGN KEY (ORG_ID) REFERENCES ORG (ID); 
+------------+-------------+----------+ 
| ID   | org_id  | name | 
+------------+-------------+ ---------+ 
| 1   | 1   | Group1 | 
| 2   | 2   | Group2 | 
| 3   | 2   | Group3 | 
+------------+-------------+----------+ 

これは更新を行いたいフィードテーブルです。 フィードに関連付けられているグループは1つのみです。

feed 
FOREIGN KEY (GROUP_ID) REFERENCES GROUPS (ID); 
+------------+-------------+--------------+ 
| ID   | org_id  | group_id | 
+------------+-------------+ -------------+ 
| 1   | 1   |  1  | 
| 2   | 2   |  2  | 
| 3   | 1   |  NULL  | 
| 4   | 2   |  3  | 
+------------+-------------+--------------+ 

だから私は解決できない1つの問題があります。私がINSERTまたはUPDATE行になったとき、groups_idを設定しましたが、組織に属していないgroups_idでもかまいません。 GROUPSのすべてのIDが有効なFK値であるため、これが発生します。それは私が避けたいものです。 insertまたはupdategroups_idの行がと同じorg_idであることだけが可能である必要があります。

ご覧のとおり、データは正常です。しかし、私がこれを作ろうとすると、エラーが発生したことをうれしく思っています。INSERT INTO feed VALUES (4, 2, 1)ええ、そうです、私は素敵なエラーがありません....

私はそれらの間を接続することは困難です。私が欠けている情報や方法があるようです。私はたくさん探してきましたが、私は自分の問題を説明する言葉を知らない。

私はあなたに質問しますか?

EDIT:

すべてのフィードと、すべてのグループが識別子を持つ組織に関連しています。組織はフィード/メッセージを作成できます。このフィードがグループに関連付けられていない場合、このフィードは公開されません。特別なフィードの場合、グループを作成できます。このグループはこの特別な組織に関連しています。

これは動作し、すべてが良いです:

UPDATE feed 
SET title = "Title", message = "Message", groups_id = "1" 
WHERE id = "1" AND org_id = "1" 

しかし、これも動作します:

UPDATE feed 
SET title = "Title", message = "Message", groups_id = "2" 
WHERE id = "1" AND org_id = "1" 

問題は、関連しているフィード(にグループを関連付けることが可能であること、ですorg 1)、グループはorgに関連付けられていません(グループ2はorg 2に関連付けられています)。

だから、私の考えは、外部キーまたは類似(チェック、結合、サブクエリ)を介してこれを解決する方法があります。または、私のdbデザインについて考えるべきですか?

+0

あなたの間違いは、最初に 'feed'に' org_id'を含んでいます。これは、 'group_id'によって' groups'テーブルから導かれるべきです。 – shmosel

+1

なぜ、orgにはidとorg_idの両方が必要ですか? – e4c5

+0

@shmosel物事は、feedsを関連付けるためにFEEDのorg_idが必要です。groups_idは指定されていません。グループにリンクされていないすべての行は、NULLであり、パブリック・グループに自動的に入ります。しかし、与えられたorg_idだけに。 – Keev

答えて

3

私はなる外部キーはあなたの問題を解決思う:

create table agroup (
    id int primary key, 
    orgid int, 
    UNIQUE (id,orgid) 
); 

create table feed (
    id int primary key, 
    groupid int, 
    orgid int, 
    FOREIGN KEY (groupid, orgid) REFERENCES agroup(id, orgid) 
); 

insert into agroup values (10, 1), (20, 1), (30, 2), (40, NULL); 
insert into feed values (100,10,1), (101, 20, 1); 
insert into feed values (102, 40, NULL); # works 
insert into feed values (103, NULL, 1); # works as well 
# insert into feed values (110,10,2); # yields error "Cannot add or update a child row: a foreign key constraint fails" 

必要であるように思われ、UNIQUE(id,orgid)に注意してください。私はagroup(id primary key)がなぜagroup(id,orgid)を一意にするのに十分でないのか分からないけれども、私はこの明示的なunique(id,orgid)制約のないコンパイラエラーを持っています。文書によれば、参照される属性は索引付けされなければならない。とにかく、あなたの問題は解決されるべきです。

EDIT:拡張された例です。この例では、参照属性のNULL値の場合も示しています。

少なくともMySQLでは、複合外部キー制約により、親テーブルに対応するNULL値を持つ行が含まれているかどうかにかかわらず、参照する(子)行にNULL値が許可されます。外部キー属性にNULL値を持つ行を挿入すると、外部キー制約は単に無視されます。 " " ... MySQLは基本的にMATCH SIMPLEで定義されたセマンティクスを実装しています。このセマンティクスは、外部キーの一部または全部をNULLにすることを許可します。その場合、そのような外部キーを含む(子テーブル)行は許可されます(親)テーブル内のどの行とも一致しません。トリガーを使用して他のセマンティクスを実装することは可能です。

+0

org_idが明らかに他のテーブルを参照するので、外来キーがこのように構成されることはありませんはい、これが正しいです! – e4c5

+0

グループ*(group_id)* IS NULLを持たない 'public'フィードのコーナーケースがあります。しかし、それはあなたの外部キーの制約を破ります。代わりに、各組織の明示的なグループが 'public'と呼ばれ、NULL値が不要になるようにしてください。 – MatBailie

+0

明日これを強くテストしますが、それは私の問題を解決するようです。大いに感謝する! @MatBailie私は思った、私はエントリを保存することができます。私はシーマを改作します。どうも。 – Keev

関連する問題