Cómo crear relaciones en MySQL

96

En clase, todos estamos 'estudiando' bases de datos y todos usan Access. Aburrido de esto, estoy tratando de hacer lo que el resto de la clase está haciendo, pero con comandos SQL sin procesar con MySQL en lugar de usar Access.

He logrado crear bases de datos y tablas, pero ahora, ¿cómo hago una relación entre dos tablas?

Si tengo mis dos tablas como esta:

CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY ( account_id )
)

y

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
    PRIMARY KEY ( customer_id )
)

¿Cómo creo una 'relación' entre las dos tablas? Quiero que a cada cuenta se le "asigne" un ID de cliente (para indicar quién es el propietario).

Josh Hunt
fuente
48
"ME NIEGO a estudiar Access, estudiaré un motor de base de datos REAL: MySQL" ¡Ese es el espíritu! Felicitaciones = D
Metafaniel
2
Tenga en cuenta que las restricciones de clave externa no implementan relaciones, implementan integridad. La asociación entre account_id y customer_id en la tabla de cuentas implementa la relación entre las respectivas entidades.
reaanb
1
"¡Ese es el espíritu!", Siempre que sea mysql con InnoDB, no MyISAM. Además, postgreqsl tiene algunas características interesantes sobre MySQL que vale la pena considerar.
jgmjgm

Respuestas:

102

Si las tablas son innodb, puede crearlas así:

CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY ( account_id ), 
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id) 
) ENGINE=INNODB;

Debe especificar que las tablas son innodb porque el motor myisam no admite claves externas. Busque aquí más información.

Eric Hogue
fuente
Vi en un artículo que no es necesario especificar la cláusula ENGINE = InnoDB si InnoDB está definido como el motor de almacenamiento predeterminado, se puede verificar usando el comando (mysql> SELECT @@ default_storage_engine;)
Arun
80

como dijo ehogue, pon esto en tu CREAR TABLA

FOREIGN KEY (customer_id) REFERENCES customers(customer_id) 

alternativamente, si ya ha creado la tabla, use un comando ALTER TABLE:

ALTER TABLE `accounts`
  ADD CONSTRAINT `FK_myKey` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`customer_id`) ON DELETE CASCADE ON UPDATE CASCADE;

Una buena forma de comenzar a aprender estos comandos es utilizando las herramientas GUI de MySQL , que le brindan una interfaz más "visual" para trabajar con su base de datos. El beneficio real de eso (sobre el método de Access) es que después de diseñar su tabla a través de la GUI, le muestra el SQL que se ejecutará y, por lo tanto, puede aprender de eso.

nickf
fuente
3
Tu respuesta es la mejor solución
Omar
14
CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY ( account_id )
)

and

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
)

How do I create a 'relationship' between the two tables? I want each account to be 'assigned' one customer_id (to indicate who owns it).

Tienes que preguntarte si esta es una relación 1 a 1 o una relación 1 entre muchos. Es decir, ¿cada cuenta tiene un cliente y cada cliente tiene una cuenta? O habrá clientes sin cuentas. Tu pregunta implica lo último.

Si desea tener una relación estricta de 1 a 1, simplemente combine las dos tablas.

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
)

En el otro caso, la forma correcta de crear una relación entre dos tablas es crear una tabla de relaciones.

CREATE TABLE customersaccounts(
    customer_id INT NOT NULL,
    account_id INT NOT NULL,
    PRIMARY KEY (customer_id, account_id)
    FOREIGN KEY customer_id references customers (customer_id) on delete cascade,
    FOREIGN KEY account_id  references accounts  (account_id) on delete cascade
}

Luego, si tiene un customer_id y desea la información de la cuenta, se une a cuentas de clientes y cuentas:

SELECT a.*
    FROM customersaccounts ca
        INNER JOIN accounts a ca.account_id=a.account_id
            AND ca.customer_id=mycustomerid;

Debido a la indexación, esto será increíblemente rápido.

También puede crear una VISTA que le brinde el efecto de la tabla de cuentas de clientes combinada mientras las mantiene separadas

CREATE VIEW customeraccounts AS 
    SELECT a.*, c.* FROM customersaccounts ca
        INNER JOIN accounts a ON ca.account_id=a.account_id
        INNER JOIN customers c ON ca.customer_id=c.customer_id;
usuario3842431
fuente
1
Creo que quiso decir ca.no ac.(3 lugares).
Vista elíptica
escribiste PRIMARY KEY (customer_id, account_id)sin una coma después
theonlygusti
11

Agregando al comentario por ehogue, debe hacer coincidir el tamaño de las claves en ambas tablas. Más bien que

customer_id INT( 4 ) NOT NULL ,

hazlo

customer_id INT( 10 ) NOT NULL ,

y asegúrese de que su columna int en la tabla de clientes también sea int (10).

Zak
fuente
7

Algunos motores MySQL admiten claves externas. Por ejemplo, InnoDB puede establecer restricciones basadas en claves externas. Si intenta eliminar una entrada en una tabla que tiene dependientes en otra, la eliminación fallará.

Si está utilizando un tipo de tabla en MySQL, como MyISAM, que no admite claves externas, no vincula las tablas en ningún lugar excepto en sus diagramas y consultas.

Por ejemplo, en una consulta, vincula dos tablas en una declaración de selección con una combinación:

SELECT a, b from table1 LEFT JOIN table2 USING (common_field);
Gary Richardson
fuente
2

Aquí hay un par de recursos que lo ayudarán a comenzar: http://www.anchor.com.au/hosting/support/CreatingAQuickMySQLRelationalDatabase y http://code.tutsplus.com/articles/sql-for-beginners-part- 3-relaciones-de-base de datos - net-8561

Además, como dijeron otros, use una GUI: intente descargar e instalar Xampp (o Wamp) que ejecutan software de servidor (Apache y mySQL) en su computadora. Luego, cuando navegue a // localhost en un navegador, seleccione PHPMyAdmin para comenzar a trabajar con una base de datos mySQL visualmente. Como se mencionó anteriormente, utilizamos innoDB para permitirle establecer las relaciones que solicitó. Hace que sea mucho más fácil ver lo que está haciendo con las tablas de la base de datos. Solo recuerde DETENER los servicios Apache y mySQL cuando termine; estos pueden abrir puertos que pueden exponerlo a piratería / amenazas maliciosas.

usuario3659515
fuente
Si configura apache y mysql para que solo atiendan solicitudes locales, no es necesario que las detenga. Además, los usuarios deben tener al menos un software de firewall instalado si instalan este tipo de servicios. Dicho esto, muchos enrutadores domésticos vienen con un firewall integrado, por lo que los puertos no deberían estar abiertos de todos modos, a menos que alguien con acceso al enrutador los haya abierto.
Chris
1

Una de las reglas que debe conocer es que la columna de la tabla a la que desea hacer referencia debe tener el mismo tipo de datos que la tabla de referencia. 2 si decide usar mysql, debe usar InnoDB Engine porque, según su pregunta, ese es el motor que respalda lo que desea lograr en mysql.

A continuación se muestra el código. Pruébelo, aunque las primeras personas en responder esta pregunta, proporcionaron respuestas excelentes al 100% y, por favor, considérelas todas.

CREATE TABLE accounts(
    account_id INT NOT NULL AUTO_INCREMENT,
    customer_id INT( 4 ) NOT NULL ,
    account_type ENUM( 'savings', 'credit' ) NOT NULL,
    balance FLOAT( 9 ) NOT NULL,
    PRIMARY KEY (account_id)
)ENGINE=InnoDB;

CREATE TABLE customers(
    customer_id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    address VARCHAR(20) NOT NULL,
    city VARCHAR(20) NOT NULL,
    state VARCHAR(20) NOT NULL,
     PRIMARY KEY ( account_id ), 
FOREIGN KEY (customer_id) REFERENCES customers(customer_id) 
)ENGINE=InnoDB; 
Musa
fuente
0
create table departement(
    dep_id      int primary key auto_increment,
    dep_name    varchar(100) not null,
    dep_descriptin      text,
    dep_photo       varchar(100) not null,
    dep_video       varchar(300) not null
);

create table newsfeeds(
    news_id         int primary key auto_increment,
    news_title      varchar(200) not null,
    news_description    text,
    news_photo          varchar(300) ,
    news_date           varchar(30) not null,
    news_video          varchar(300),
    news_comment        varchar(200),
    news_departement    int foreign key(dep_id) references departement(dep_id)
);
Anayat
fuente
Proporcione una explicación sobre el esquema que proporcionó.
samabcde