Tablolar tasarlanırken bire bir, bire çok ve çoktan çoğa ilişkiler nasıl uygulanır?


281

Herkes bazı örneklerle tablolar tasarlarken bire bir, bire çok ve çoktan çoğa ilişkilerin nasıl uygulanacağını açıklayabilir mi?


Uygulama, hedef RDBMS'ye göre değişiklik gösterir, bu nedenle hangi sağlayıcıyı hedefliyorsunuz?
billinkc

1
bu bir ödev sorusu değil ... !! Bir röportaj için hazırlanıyorum .. Bu yüzden burada sormayı düşündüm ... Googling denedim ama tüm bunları bir açıklamak nerede iyi bir makale bulamadık ... !!
cephanelik

Ben oracle veritabanı hedefliyoruz .. !!
cephanelik

Bu yazıyı da okumak isteyebilirsiniz .... stevencalise.wordpress.com/2010/09/01/… 2. ve 3. noktalara çok dikkat ediyorum.
tsells

3
@tsells Bazen özgeçmişinizde veya doğrudan iş gereklilikleri için geçerli olmayan sorular sorulur. Bana bir şirkette röportaj yapacak olanların bir listesi verildi ve biri de bir DB uzmanıydı. Özgeçmişimde SQL yoktu, ancak birkaç basit SQL sorgusunu fırçaladım. İşe yaradı ve işi aldım. Sınırlarını kabul ediyorlar mı yoksa yollarını taklit ediyorlar mı? Limitlerini kabul ederlerse, yine de deniyorlar mı yoksa çok erken mi vazgeçiyorlar?
Doug Cuthbertson

Yanıtlar:


478

Bire bir: Başvurulan tabloya yabancı anahtar kullanın:

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

Ayrıca addess.student_id, alt tablodaki ( address) birden çok satırın başvurulan tablodaki ( student) aynı satırla ilişkilendirilmesini önlemek için yabancı anahtar sütununa ( ) benzersiz bir kısıtlama koymanız gerekir .

Bire çok : İlişkinin birçok tarafında "bir" tarafa bağlanan bir yabancı anahtar kullanın:

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

Çoktan çoğa : Bir bağlantı tablosu kullanın ( örnek ):

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

Örnek sorgular:

 -- 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
Bire Bir ilişkisinde "geri bağlantı" yararlı olduğunda bunun iyi bir örneği nedir? Açık ve özlü cevap için teşekkürler.
dev_feed

1
@dev_feed Veritabanı tasarımı açısından, bağlantının yararlı olduğunu görmüyorum, ancak yukarıdaki bağlantıyı kullanmak, studentverilen bir address.
edhedges

@NullUserException, çoktan çoğa ilişki için 3 tabloya ihtiyacımız var. Çok tablodan çok ilişkiye iki tablo tarafından yapılamaz.

1
@Cody Her student_classessatırın yalnızca bire bir ilişkisi olmalıdır. İçinde ve varsa studentA, iki satır olmalı , biri ilişki için. classAclassBstudent_classes
NullUserException

11
Bire bir ilişkide, birleştirme alanı her iki tabloda da benzersiz olmalıdır. Muhtemelen bir tabloda benzersizliği garanti eden bir PK'dır, ancak diğer tabloda benzersiz bir dizine ihtiyaç duyabilir.
HLGEM

70

İlişki türlerinin bazı gerçek dünya örnekleri:

Bire bir (1: 1)

Bir ilişki, ancak tablo A'daki bir kayıt tablo B'deki en fazla bir kayıtla ilgiliyse bire birdir.

Bire bir ilişki kurmak için, B tablosunun birincil anahtarı (yetim kaydı olmadan) A tablosunun (yetim kayıtları ile) ikincil anahtarı olmalıdır.

Örneğin:

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);

Bire çok (1: M)

Bir ilişki, ancak tablo A'daki bir kayıt tablo B'deki bir veya daha fazla kayıtla ilişkiliyse bire çok olur. Ancak, tablo B'deki bir kayıt tablo A'daki birden fazla kayıtla ilişkilendirilemez.

Bir-çok ilişkisi oluşturmak için A tablosunun birincil anahtarı ("bir" tablo) B tablosunun ikincil anahtarı ("çok" tablosu) olmalıdır.

Örneğin:

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
);

Çoktan çoğa (M: M)

Bir ilişki, yalnızca tablo A'daki bir kayıt tablo B'deki bir veya daha fazla kayıtla ilişkiliyse ve bunun tersi olduğunda çoktan çoğa ilişkilidir.

Çoktan çoğa ilişki kurmak için, hem A tablosunun hem de B tablosunun birincil anahtarlarına sahip olacak "ClassStudentRelation" adlı üçüncü bir tablo oluşturun.

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)
);

1. örnek: GID numarası (6) ve SGID Numarası (4), neden? SGID de (6) olmamalı mı? Ve 2. örnek numarasında (4) ve numara (2) ...
obeliksz

@obeliksz boş olabilir mi?
moo inek

Neden M: N sonunda UNIQUE (StudentID, ClassID) kullanıyorsunuz?
strix25

1
@ strix25 Aynı ClassStudentRelation satırını birden çok kez oluştururken tekrardan kaçınmayı zorlamak için, hem StudentID hem de ClassID yabancı anahtarlarının benzersiz olduğundan emin değilseniz, aynı StudentID ve ClassID ile yeni bir satır oluşturmayı bırakan nedir? çünkü yukarıdaki kodda benzersiz değillerdir. Böylece, yukarıdaki kod gibi uygular veya ClassStudentRelation öğesinde aynı satırı oluşturmanın tekrarlanmasını önlemek için hem StudentID hem de ClassID içeren bir birincil anahtar eklersiniz.
Fouad Boukredine

1
@valik Veritabanlarındaki veriler, mevcut verilere başvurarak çalışır ve aynı veri parçasını birden çok kez oluşturmaz, neden bunu yapasınız? Tabii ki yapmak zorunda değilsiniz, aksi takdirde verimli değildir. Bunu göz önünde bulundurarak, örneğinize geri dönelim (james biyolojiye sahiptir ve biyolojinin james'e sahiptir), Tabii ki, veritabanında zaten var olan başka bir veri parçası oluşturmadan da yapabilirsiniz. Tek yapmanız gereken, herhangi bir ilişki oluşturmak istediğinizde mevcut olana başvurmaktır. Umarım bu yardımcı olur :)
Fouad Boukredine

8

Bu çok yaygın bir soru, bu yüzden bu cevabı bir makaleye dönüştürmeye karar verdim .

Bire birçok

Bir-çok tablo ilişkisi aşağıdaki gibi görünür:

Bire birçok

İlişkisel veritabanı sisteminde, bire çok tablo ilişkisi , alt tablodaki üst tablo satırına Foreign Keybaşvuruda bulunan sütunu temel alan iki tabloyu birbirine bağlar Primary Key.

Yukarıdaki tablo diyagramda, post_idsütun post_commenttablo bir sahiptir Foreign Keyilişki posttablosu id Primary Keysütun:

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

Bire bir

Bire bir tablo ilişkisi aşağıdaki gibidir:

Bire bir

İlişkisel veritabanı sisteminde, bire bir tablo ilişkisi , alt tablodaki ana tablo satırına Primary Keyda Foreign Keybaşvuran bir sütunu temel alan iki tabloyu birbirine bağlar Primary Key.

Bu nedenle, alt tablonun Primary Keyana tabloyla paylaştığını söyleyebiliriz .

Yukarıdaki tablo diyagramda, idsütun post_detailstablo da var Foreign Keyolan ilişkiyi posttablo id Primary Keysütun:

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

Birçok çoğa

Çoktan çoğa tablo ilişkisi şöyle görünür:

Birçok çoğa

İlişkisel veritabanı sisteminde, çoktan çoğa tablo ilişkisi , iki üst tabloyu, iki üst tablodaki Foreign Keysütunlara başvuran iki sütun içeren bir alt tablo aracılığıyla bağlar Primary Key.

Yukarıdaki tablo diyagramda, post_idsütun post_tagtablo da var Foreign Keyolan ilişkiyi posttablo id Primary Keysütun:

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

Ve, tag_idsütun post_tagtabloda bir sahip Foreign Keyile ilişki tagtablo id Primary Keysütununun:

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

3

Bire bir (1-1) ilişki: Bu, birincil ve yabancı anahtar (yabancı anahtarla ilgili birincil anahtar yalnızca bir kayıt) arasındaki ilişkidir. bu birebir ilişkidir.

Bire Çok (1-M) ilişki: Bu aynı zamanda birincil ve yabancı anahtar ilişkileri arasındaki ilişkidir, ancak burada birden fazla kayıtla ilgili birincil anahtar (yani Tablo A'da kitap bilgisi vardır ve Tablo B'de bir kitabın birden çok yayıncısı vardır).

Çoktan Çoğa (MM): Çoktan çoğa, aşağıdaki örnekle tam olarak açıklanan iki boyut içerir.

-- 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
Birincil anahtar ve yabancı anahtar kısıtlamaları da eklemiş olsaydınız daha iyi ve daha açık olurdu.
Ashish K Gupta
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.