テーブルを設計するときに、1対1、1対多、および多対多の関係を実装する方法は?


281

いくつかの例を使用してテーブルを設計するときに、1対1、1対多、および多対多の関係を実装する方法を誰かが説明できますか?


実装はターゲットRDBMSによって異なる傾向があるため、どのベンダーをターゲットにしていますか?
billinkc

1
それは宿題ではありません... !! 私はインタビューの準備をしています。ここで尋ねようと思ったのですが...グーグルで検索してみましたが、これらすべてを1つにまとめた良い記事はありませんでした... !!
アーセナル2011

私はオラクルデータベースをターゲットにしています。
アーセナル2011

この投稿も読んでみてください。... stevencalise.wordpress.com/2010/09/01/… ポイント2と3に細心の注意を払います
tsells

3
@tsellsときどき、履歴書に直接当てはまらない質問や、仕事の要件に直接当てはまらない質問が表示されます。1つの会社で面接を受ける人のリストが与えられ、1つはDBの専門家でした。履歴書にはSQLがありませんでしたが、いくつかの単純なSQLクエリをブラッシュアップしました。それは助けになり、私は仕事を手に入れました。後で知りました、採用マネージャーは候補者がプレッシャーの下でどのように反応するか心配していました。彼らは自分の限界を認めるか、それとも自分の道を偽っているか?彼らが限界を認めるなら、彼らはとにかく試みたり、あきらめたりしますか?
Doug Cuthbertson

回答:


478

1対1:参照されるテーブルへの外部キーを使用します。

student: student_id, first_name, last_name, address_id
address: address_id, address, city, zipcode, student_id # you can have a
                                                        # "link back" if you need

またaddess.student_id、子テーブル(address)の複数の行が参照されるテーブル(student)の同じ行に関連付けられないように、外部キー列()に一意制約を設定する必要があります。

1対多:関係の多面で外部キーを使用して、「1」面にリンクします。

teachers: teacher_id, first_name, last_name # the "one" side
classes:  class_id, class_name, teacher_id  # the "many" side

多対多:ジャンクションテーブルを使用します():

student: student_id, first_name, last_name
classes: class_id, name, teacher_id
student_classes: class_id, student_id     # the junction table

クエリの例:

 -- Getting all students for a class:

    SELECT s.student_id, last_name
      FROM student_classes sc 
INNER JOIN students s ON s.student_id = sc.student_id
     WHERE sc.class_id = X

 -- Getting all classes for a student: 

    SELECT c.class_id, name
      FROM student_classes sc 
INNER JOIN classes c ON c.class_id = sc.class_id
     WHERE sc.student_id = Y


1
「リンクバック」が1対1の関係で役立つ場合の良い例は何ですか?明確かつ簡潔な回答をありがとう。
dev_feed 2014年

1
@dev_feedデータベース設計の点では、戻るリンクが有益であるとは思いませんが、上のリンクの例を使用すると、student特定のを簡単に見つけることができaddressます。
edhedges 2014

@NullUserException多対多のリレーションシップには3つのテーブルが必要です。多対多のリレーションシップで2つのテーブルを使用できませんか。

1
@Cody student_classes各行には、1対1の関係が1つだけ必要です。場合studentAであるclassAclassB、その後に2つの行があるはずstudent_classes、その関係について1。
NullUserException

11
1対1の関係では、結合フィールドは両方のテーブルで一意である必要があります。一意性を保証する1つのテーブルのPKである可能性がありますが、他のテーブルに一意のインデックスが必要な場合があります。
HLGEM

70

次に、関係のタイプの実際の例をいくつか示します。

1対1(1:1)

テーブルAの1つのレコードがテーブルBの最大1つのレコードに関連付けられている場合に限り、関係は1対1です。

1対1の関係を確立するには、(孤立レコードのない)テーブルBの主キーが(孤立レコードのある)テーブルAの二次キーでなければなりません。

例えば:

CREATE TABLE Gov(
    GID number(6) PRIMARY KEY, 
    Name varchar2(25), 
    Address varchar2(30), 
    TermBegin date,
    TermEnd date
); 

CREATE TABLE State(
    SID number(3) PRIMARY KEY,
    StateName varchar2(15),
    Population number(10),
    SGID Number(4) REFERENCES Gov(GID), 
    CONSTRAINT GOV_SDID UNIQUE (SGID)
);

INSERT INTO gov(GID, Name, Address, TermBegin) 
values(110, 'Bob', '123 Any St', '1-Jan-2009');

INSERT INTO STATE values(111, 'Virginia', 2000000, 110);

1対多(1:M)

テーブルAの1つのレコードがテーブルBの1つ以上のレコードに関連付けられている場合に限り、リレーションシップは1対多です。ただし、テーブルBの1つのレコードをテーブルAの複数のレコードに関連付けることはできません。

1対多の関係を確立するには、テーブルA(「1」のテーブル)の主キーがテーブルB(「多」のテーブル)の2次キーでなければなりません。

例えば:

CREATE TABLE Vendor(
    VendorNumber number(4) PRIMARY KEY,
    Name varchar2(20),
    Address varchar2(20),
    City varchar2(15),
    Street varchar2(2),
    ZipCode varchar2(10),
    Contact varchar2(16),
    PhoneNumber varchar2(12),
    Status varchar2(8),
    StampDate date
);

CREATE TABLE Inventory(
    Item varchar2(6) PRIMARY KEY,
    Description varchar2(30),
    CurrentQuantity number(4) NOT NULL,
    VendorNumber number(2) REFERENCES Vendor(VendorNumber),
    ReorderQuantity number(3) NOT NULL
);

多対多(M:M)

テーブルAの1つのレコードがテーブルBの1つ以上のレコードに関連付けられている場合、およびその逆の場合に限り、関係は多対多です。

多対多の関係を確立するには、「ClassStudentRelation」という3番目のテーブルを作成します。このテーブルには、テーブルAとテーブルBの両方の主キーがあります。

CREATE TABLE Class(
    ClassID varchar2(10) PRIMARY KEY, 
    Title varchar2(30),
    Instructor varchar2(30), 
    Day varchar2(15), 
    Time varchar2(10)
);

CREATE TABLE Student(
    StudentID varchar2(15) PRIMARY KEY, 
    Name varchar2(35),
    Major varchar2(35), 
    ClassYear varchar2(10), 
    Status varchar2(10)
);  

CREATE TABLE ClassStudentRelation(
    StudentID varchar2(15) NOT NULL,
    ClassID varchar2(14) NOT NULL,
    FOREIGN KEY (StudentID) REFERENCES Student(StudentID), 
    FOREIGN KEY (ClassID) REFERENCES Class(ClassID),
    UNIQUE (StudentID, ClassID)
);

最初の例:GID番号(6)とSGID番号(4)、なぜですか?SGIDも(6)にすべきではありませんか?そして2番目の例では、number(4)とnumber(2)...
obeliksz 2018

@obelikszはnullになる可能性がありますか?
moo牛

M:Nの末尾にUNIQUE(StudentID、ClassID)を使用するのはなぜですか?
strix25

1
@ strix25同じClassStudentRelation行を複数回作成するときに繰り返しを回避するように強制するには、外部キーStudentIDとClassIDの両方が一意でないことを確認すると、同じStudentIDとClassIDを持つ新しい行の作成が停止しますか?上記のコードでは一意ではないためです。したがって、上記のコードのように実装するか、StudentIDとClassIDの両方を含む主キーを追加して、ClassStudentRelationで同じ行を繰り返し作成しないようにします。
Fouad Boukredine

1
@valikデータベース内のデータは、既存のデータを参照し、同じデータを何度も作成しないことで機能しますが、なぜそれを行うのですか?もちろん、そうする必要はありません。そうでなければ効率的ではありません。それを念頭に置いて、例に戻りましょう(jamesには生物学があり、biologyにはjamesがあります)。もちろん、データベースにすでに存在する別のデータを作成しなくても可能です。必要なのは、関係を作成するときに、既存の参照を参照することだけです。それがお役に立てば幸いです:)
Fouad Boukredine

8

これは非常に一般的な質問なので、この回答を記事に変えることにしました。

1対多

1対多のテーブルの関係は次のようになります。

1対多

リレーショナルデータベースシステムでは、1対多のテーブルリレーションシップは、親テーブル行のForeign Keyを参照する子の列に基づいて2つのテーブルをリンクしますPrimary Key

上記の表の図では、post_idpost_commentテーブルが有しているForeign Keyとの関係postテーブルID Primary Keyカラム:

ALTER TABLE
    post_comment
ADD CONSTRAINT
    fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post

1対1

1対1のテーブルの関係は次のようになります。

1対1

リレーショナルデータベースシステムでは、1対1のテーブルリレーションシップが、親テーブル行の参照Primary Keyでもある子の列に基づいて2つのテーブルをリンクします。Foreign KeyPrimary Key

したがって、子テーブルPrimary Keyは親テーブルと共有していると言えます。

上の表の図idでは、post_details表の列は表Foreign Keyとの関係も持っていpostますid Primary Key列を:

ALTER TABLE
    post_details
ADD CONSTRAINT
    fk_post_details_id
FOREIGN KEY (id) REFERENCES post

多対多

多対多のテーブルの関係は次のようになります。

多対多

リレーショナルデータベースシステムでは、多対多のテーブルリレーションシップは、2つの親テーブルを、2つの Foreign Key列を参照する列Primary Key

上記の表の図post_idでは、post_tag表の列はForeign Keypost表ID Primary Key列との関係も持っています。

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post

そして、tag_idpost_tagの表では、持っているForeign Keyとの関係tagテーブルのid Primary Key列を:

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag

3

1対1(1-1)の関係: これは、主キーと外部キーの関係です(主キーは1つのレコードのみの外部キーに関連しています)。これは1対1の関係です。

1対多(1-M)の関係: これも主キーと外部キーの関係間の関係ですが、ここでは複数のレコードに関連する主キーがあります(つまり、表Aには書籍情報があり、表Bには1つの書籍の複数の出版社があります)。

多対多(MM):多対多には2つの次元が含まれ、サンプルを使用して以下で完全に説明されています。

-- This table will hold our phone calls.
CREATE TABLE dbo.PhoneCalls
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CallTime DATETIME NOT NULL DEFAULT GETDATE(),
   CallerPhoneNumber CHAR(10) NOT NULL
)
-- This table will hold our "tickets" (or cases).
CREATE TABLE dbo.Tickets
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CreatedTime DATETIME NOT NULL DEFAULT GETDATE(),
   Subject VARCHAR(250) NOT NULL,
   Notes VARCHAR(8000) NOT NULL,
   Completed BIT NOT NULL DEFAULT 0
)
-- This table will link a phone call with a ticket.
CREATE TABLE dbo.PhoneCalls_Tickets
(
   PhoneCallID INT NOT NULL,
   TicketID INT NOT NULL
)

8
主キーと外部キーの制約も追加した方が良かったでしょう。
Ashish K Gupta 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.