¿Cómo implementar relaciones uno a uno, uno a muchos y muchos a muchos al diseñar tablas?


281

¿Alguien puede explicar cómo implementar relaciones uno a uno, uno a muchos y muchos a muchos mientras diseña tablas con algunos ejemplos?


La implementación tiende a variar según el RDBMS objetivo, entonces, ¿a qué proveedor se dirige?
billinkc

1
esa no es una pregunta de tarea ... !! Me estoy preparando para una entrevista ... Así que pensé en preguntar aquí ... ¡Intenté buscar en Google pero no encontré ningún buen artículo donde me explicaran todo esto en uno ...!
arsenal el

Estoy apuntando a la base de datos Oracle .. !!
arsenal el

Es posible que desee leer esta publicación también ... stevencalise.wordpress.com/2010/09/01/… Prestaría mucha atención a los puntos 2 y 3.
tsells

3
@tsells A veces se le hacen preguntas que no se aplican a lo que figura en su currículum o directamente a los requisitos del trabajo. Me dieron una lista de personas que me iban a entrevistar en una empresa, y una era experta en DB. No tenía SQL en mi currículum, pero repasé algunas consultas simples de SQL. Me ayudó y conseguí el trabajo. Más tarde descubrí que al gerente de contratación le preocupaba cómo los candidatos respondían bajo presión. ¿Admiten sus límites o falsifican su camino? Si admiten sus límites, ¿lo intentan de todos modos o se rinden demasiado pronto?
Doug Cuthbertson

Respuestas:


479

Uno a uno: use una clave foránea para la tabla referenciada:

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

También debe poner una restricción única en la columna de clave externa ( addess.student_id) para evitar que varias filas en la tabla secundaria ( address) se relacionen con la misma fila en la tabla referenciada ( student).

Uno a muchos : use una clave externa en el lado múltiple de la relación que se vincula al lado "uno":

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

Muchos a muchos : use una tabla de unión ( ejemplo ):

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

Consultas de ejemplo:

 -- 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
¿Cuál es un buen ejemplo de cuándo el "enlace de regreso" es útil en la relación uno a uno? Gracias por la respuesta clara y concisa.
dev_feed

1
@dev_feed En términos de diseño de la base de datos, no veo que el enlace de regreso sea beneficioso, pero usar el ejemplo anterior puede simplificar la búsqueda de un studentdado address.
bordes el

@NullUserException, debemos necesitar 3 tablas para la relación de muchos a muchos. No se puede hacer con dos tablas de la relación de muchos a muchos.

1
@Cody Cada student_classesfila solo debe tener una relación uno a uno. Si studentAestá adentro classAy classB, entonces debería haber dos filas adentro student_classes, una para cuál relación.
NullUserException

11
En una relación uno a uno, el campo de unión debe ser único en ambas tablas. Es probable que sea una PK en una tabla que garantiza la unicidad, pero puede necesitar un índice único en la otra tabla.
HLGEM

70

Aquí hay algunos ejemplos del mundo real de los tipos de relaciones:

Uno a uno (1: 1)

Una relación es uno a uno si y solo si un registro de la tabla A está relacionado con un máximo de un registro en la tabla B.

Para establecer una relación uno a uno, la clave primaria de la tabla B (sin registro huérfano) debe ser la clave secundaria de la tabla A (con registros huérfanos).

Por ejemplo:

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

Uno a muchos (1: M)

Una relación es uno a muchos si y solo si un registro de la tabla A está relacionado con uno o más registros en la tabla B. Sin embargo, un registro en la tabla B no puede estar relacionado con más de un registro en la tabla A.

Para establecer una relación uno a muchos, la clave primaria de la tabla A (la tabla "uno") debe ser la clave secundaria de la tabla B (la tabla "muchos").

Por ejemplo:

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

Muchos a muchos (M: M)

Una relación es de muchos a muchos si y solo si un registro de la tabla A está relacionado con uno o más registros de la tabla B y viceversa.

Para establecer una relación de muchos a muchos, cree una tercera tabla llamada "ClassStudentRelation" que tendrá las claves principales de la tabla A y la tabla 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)
);

1er ejemplo: número GID (6) y número SGID (4), ¿por qué? ¿No debería ser también SGID (6)? Y en el segundo ejemplo número (4) y número (2) ...
obeliksz

@obeliksz podrían ser nulos?
vaca MOO

¿Por qué usarías UNIQUE (StudentID, ClassID) al final de M: N?
strix25

1
@ strix25 Para exigir que se evite la repetición al crear la misma fila ClassStudentRelation varias veces, porque si no se asegura de que ambas claves externas StudentID y ClassID sean únicas, ¿qué deja de crear una nueva fila con el mismo StudentID y ClassID? ya que no son únicos en el código anterior. Por lo tanto, puede implementarlo como el código anterior o agregar una clave principal que incluya tanto StudentID como ClassID para evitar la repetición de crear la misma fila en ClassStudentRelation.
Fouad Boukredine

1
@valik Los datos en las bases de datos funcionan haciendo referencia a los datos existentes y no creando la misma pieza de datos varias veces, ¿por qué haría eso? por supuesto que no tiene que hacerlo, de lo contrario no es eficiente. Con eso en mente, volvamos a su ejemplo (James tiene biología y la biología tiene James), por supuesto que puede, PERO sin crear otro dato que ya exista en la base de datos. Todo lo que necesita hacer es hacer referencia a la ya existente cada vez que desee crear una relación. Espero que ayude :)
Fouad Boukredine

8

Esta es una pregunta muy común, así que decidí convertir esta respuesta en un artículo .

Uno a muchos

La relación de la tabla uno a muchos se ve de la siguiente manera:

Uno a muchos

En un sistema de base de datos relacional, una relación de tabla de uno a muchos vincula dos tablas basadas en una Foreign Keycolumna en el elemento secundario que hace referencia a la Primary Keyfila de la tabla principal.

En el diagrama de la tabla anterior, la post_idcolumna de la post_commenttabla tiene una Foreign Keyrelación con la columna de postid de la tabla Primary Key:

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

Doce y cincuenta y nueve de la noche

La relación de la tabla uno a uno se ve de la siguiente manera:

Doce y cincuenta y nueve de la noche

En un sistema de base de datos relacional, una relación de tabla uno a uno vincula dos tablas basadas en una Primary Keycolumna en el elemento secundario que también hace Foreign Keyreferencia a la Primary Keyfila de la tabla principal.

Por lo tanto, podemos decir que la tabla secundaria comparte Primary Keycon la tabla primaria.

En el diagrama de la tabla anterior, la idcolumna de la post_detailstabla también tiene una Foreign Keyrelación con la columna de la posttabla id Primary Key:

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

Muchos a muchos

La relación de tabla de muchos a muchos se ve de la siguiente manera:

Muchos a muchos

En un sistema de base de datos relacional, una relación de tabla de muchos a muchos vincula dos tablas principales a través de una tabla secundaria que contiene dos Foreign Keycolumnas que hacen referencia a las Primary Keycolumnas de las dos tablas principales.

En el diagrama de la tabla anterior, la post_idcolumna de la post_tagtabla también tiene una Foreign Keyrelación con la columna de postID de la tabla Primary Key:

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

Y, la tag_idcolumna en la post_tagtabla tiene una Foreign Keyrelación con la columna tagid de la tabla Primary Key:

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

3

Relación uno a uno (1-1): Esta es la relación entre la clave primaria y la clave externa (la clave primaria relacionada con la clave externa es solo un registro). Esta es una relación uno a uno.

Relación de uno a muchos (1-M): Esta también es la relación entre las relaciones de claves primarias y externas, pero aquí la clave principal se relaciona con registros múltiples (es decir, la Tabla A tiene información del libro y la Tabla B tiene varios publicadores de un libro).

Many to Many (MM): Many to many incluye dos dimensiones, explicadas completamente a continuación con la muestra.

-- 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
Hubiera sido mejor y más claro si también hubiera agregado restricciones de clave primaria y clave externa.
Ashish K Gupta
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.