sql >> Base de Datos >  >> Database Tools >> phpMyAdmin

Cómo configurar la relación entre tablas en phpMyAdmin

La restricción de clave externa de la tabla 2 significa que cualquier valor de ID de cliente de la tabla 2 debe aparecer como ID de cliente en la tabla 1. Recibe el error porque está insertando un ID de cliente en la tabla 2 que no aparece en la tabla 1.

Dado que el DBMS genera los ID de cliente de la tabla 1 por incremento automático, si inserta una fila, debe obtener ese valor para insertar una fila con ese ID de cliente en la tabla 2.

Supongo que dices "Ya establecí una relación entre table1 y table2" para decir "Declaré una restricción de clave externa". Y supongo que piensa que eso significa "después de que inserte en la tabla 1, el DBMS usará el valor de la clave generada automáticamente como el valor de la clave externa cuando inserte en la tabla 2". Pero no significa eso. Tienes que hacerlo tú mismo. La restricción de clave externa simplemente significa que el DBMS verifica que cada valor de ID de cliente de la tabla 2 aparezca como un valor de ID de cliente de la tabla 1.

Puede y debe usar cualquier valor de clave previamente insertado como el valor correspondiente cuando inserta en una tabla con una clave externa a esa clave.

Para recuperar el valor de clave incrementado automáticamente generado por DBMS, use LAST_INSERT_ID() :

INSERT INTO table1 (CustomerName,Address,State)
VALUES('value1','value2','value3');
INSERT INTO table2 (customerId,product,cost)
VALUES(LAST_INSERT_ID(),'valueA','valueB');

Esto es para lo que es. Pero aquí están los problemas si no lo usas.

Primero, si no está en una transacción serializada, debe usar LAST_INSERT_ID(). Porque después de la inserción de su tabla 1, pero antes de la inserción de su tabla 2, otros podrían haber agregado filas y/o filas eliminadas, incluida su nueva fila y/o filas modificadas, incluida su nueva fila. Por lo tanto, no puede confiar en consultar la tabla 1 después de que su inserción obtenga algún valor de ID de cliente que sepa que agregó.

En segundo lugar, suponga que está en una transacción serializada y no usa LAST_INSERT_ID().

Si (CustomerName,Address,State) también es una superclave de table1, es decir, sus valores son únicos, es decir, SQL UNIQUE/KEY/PK se declara en todas o algunas de sus columnas, luego puede usarlo para consultar el nuevo ID de cliente asociado:

set @customerId = (
    SELECT customerId
    FROM table1
    WHERE CustomerName = 'value1'
    AND Address = 'value2'
    AND State = 'value3');
INSERT INTO table2 (customerId,product,cost)
VALUES(@customerId,'valueA','valueB');

Pero si (CustomerName,Address,State) no es una superclave de table1 entonces no puedes hacer esto. Porque otras filas que son duplicados para esa subfila podrían estar en la tabla1. Entonces podría recuperar varias filas. Así que no sabrías cuál es el más nuevo. En su lugar, debe consultar la tabla 1 antes de la inserción, luego insertar y luego encontrar la diferencia entre los conjuntos de ID de cliente antiguos y nuevos:

CREATE TEMPORARY TABLE table1old (
    customerId (int) PRIMARY KEY
    );
INSERT INTO table1old
SELECT customerId FROM table1;

INSERT INTO table1 (CustomerName,Address,State)
VALUES('value1','value2','value3');

set @customerId = (
    SELECT customerId
    FROM table1
    WHERE CustomerName NOT IN table1old);
INSERT INTO table2 (customerId,product,cost)
VALUES(@customerId,'valueA','valueB');

Simplemente use LAST_INSERT_ID().

PD:Curiosamente, dadas las definiciones de la tabla, idealmente se podría escribir:

INSERT INTO (
    SELECT CustomerName,Address,State,A,B
    FROM table1 JOIN table2
    USING (CustomerId))
VALUES('value1','value2','value3','valueA','valueB')

ya que solo hay un par de nuevos valores de tabla 1 y tabla 2 que pueden resultar. Hay algunas actualizaciones legales a través de vistas en SQL, aunque actualmente ninguna involucra varias tablas en MySQL