es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Al crear una entrada en una tabla, se requiere crear una entrada en exactamente una de las tablas correspondientes.

Digamos que tengo una tabla A, que se considera una tabla de “superclase” para las tablas B1, B2, …, Bn.

Esta relación es disyuntiva y total. Es decir, cada vez que se crea una entrada en la tabla A, debe crearse una entrada correspondiente en exactamente una de las tablas B1, B2, …, Bn.

Cabe destacar que cada entrada en B1, …, Bn tiene una clave externa que señala a su entrada correspondiente en A.

Mi pregunta es cómo puedo implementar esto en MySQL.


Mi idea potencial es tener una columna ENUM (llamada subclass) en la tabla A que corresponda a la tabla de la subclase que se debe crear. Luego, habría disparadores que se activan en las siguientes situaciones:

  1. Se inserta una entrada en la tabla A.
  2. Se modifican uno o más atributos de ID en la tabla A.
  3. Se modifican uno o más atributos de subclass en la tabla A.

Al activarse un disparador, dependiendo del valor de subclass, se le solicita al usuario crear una entrada en la tabla correspondiente de B1, B2, …, Bn.

Me gustaría proporcionar un ejemplo, pero tengo dificultades significativas para encontrar cómo el usuario podría especificar los valores en la entrada insertada en una de las tablas B1, B2, …, Bn. No estoy seguro de si este problema se puede resolver incluso utilizando disparadores debido a este problema.

Edición: Esta pregunta no es un duplicado de esta pregunta porque ni la pregunta ni la respuesta discuten el problema principal mencionado en la pregunta. Es decir, la restricción de que cada vez que se crea una entrada en la tabla A, debe crearse una entrada correspondiente en una de las tablas “subclase” B1, …, Bn.

Edición 2: En mi situación particular, hay una tabla paciente, que tiene tablas de “subclase” paciente_adulto y paciente_infantil.

La tabla paciente contiene todos los atributos que tanto paciente_adulto como paciente_infantil tienen, como nombre, apellido, fecha de nacimiento, etc.

La tabla paciente_adulto tiene algunos atributos propios, como telefono_principal y correo_electronico_principal. La tabla paciente_infantil se enlaza con una tabla de tutor donde cada fila de tutor contiene telefono_principal, correo_electronico_principal, etc.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para hacer cumplir la relación disyuntiva y total entre la tabla A y las tablas B1, B2, …, Bn en MySQL, una aproximación podría ser utilizar una combinación de claves foráneas, disparadores y procedimientos almacenados.

    Primero, crear la tabla A con una clave primaria id y una columna ENUM llamada subclass que especifique la tabla de subclase correspondiente para crear una entrada. Por ejemplo:

    CREATE TABLE A (
      id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
      subclass ENUM('B1', 'B2', ..., 'Bn') NOT NULL
    );
    

    A continuación, crear las tablas B1, B2, …, Bn con una restricción de clave foránea que haga referencia a la clave primaria de la tabla A. Por ejemplo:

    CREATE TABLE B1 (
      id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
      a_id INT UNSIGNED NOT NULL,
      FOREIGN KEY (a_id) REFERENCES A (id)
    );
    

    Repetir esto para las tablas B2, …, Bn.

    Para hacer cumplir la relación disyuntiva y total, crear un disparador en la tabla A que se active en la inserción o actualización. El disparador deberá comprobar si existe una entrada en la tabla de subclase correspondiente (por ejemplo, B1) para la nueva entrada insertada o actualizada en la tabla A. Si no existe, el disparador deberá llamar a un procedimiento almacenado que solicite al usuario crear una entrada en la tabla de subclase correspondiente. Por ejemplo:

    DELIMITER //
    CREATE TRIGGER enforce_disjunctive_total
    AFTER INSERT ON A
    FOR EACH ROW
    BEGIN
      DECLARE subclass_table VARCHAR(50);
      SET subclass_table = CONCAT('B', NEW.subclass);
      IF NOT EXISTS (SELECT * FROM subclass_table WHERE a_id = NEW.id) THEN
        CALL create_subclass_entry(subclass_table, NEW.id);
      END IF;
    END//
    DELIMITER ;
    
    CREATE TRIGGER enforce_disjunctive_total
    AFTER UPDATE ON A
    FOR EACH ROW
    BEGIN
      DECLARE subclass_table VARCHAR(50);
      SET subclass_table = CONCAT('B', NEW.subclass);
      IF NOT EXISTS (SELECT * FROM subclass_table WHERE a_id = NEW.id) THEN
        CALL create_subclass_entry(subclass_table, NEW.id);
      END IF;
    END//
    

    El procedimiento almacenado create_subclass_entry debe solicitar al usuario proporcionar la información necesaria para crear una entrada en la tabla de subclase correspondiente. Por ejemplo:

    CREATE PROCEDURE create_subclass_entry (IN subclass_table VARCHAR(50), IN a_id INT UNSIGNED)
    BEGIN
      IF subclass_table = 'B1' THEN
        -- solicitar al usuario la información para crear una entrada en B1
        INSERT INTO B1 (a_id, ...) VALUES (a_id, ...);
      ELSEIF subclass_table = 'B2' THEN
        -- solicitar al usuario la información para crear una entrada en B2
        INSERT INTO B2 (a_id, ...) VALUES (a_id, ...);
      END IF;
    END;
    

    Ten en cuenta que las solicitudes al usuario pueden depender de las columnas específicas y las relaciones entre la tabla A y las tablas B1, B2, …, Bn.

    Con este enfoque, cada vez que se crea o actualiza una entrada en la tabla A, debe crearse una entrada correspondiente en exactamente una de las tablas B1, B2, …, Bn. El enfoque utiliza restricciones de clave foránea para garantizar la integridad referencial, disparadores para hacer cumplir la relación disyuntiva y total, y procedimientos almacenados para solicitar al usuario la información necesaria.

Comments are closed.