sql >> Base de Datos >  >> RDS >> Mysql

Restricción de tabla cruzada de MySQL

Puede utilizar una tabla de "tipo":

CREATE TABLE Type
  ( type_code CHAR(1) NOT NULL
  , PRIMARY KEY (type_code)
  ) ;

con exactamente 2 filas (tantas como las diferentes tablas de subtipos que necesite:

INSERT INTO Type (type_code)
VALUES ('B'), ('C') ;

La tabla de supertipos (que incluye una columna que hace referencia a "Tipo"):

CREATE TABLE A
  ( a_id INT NOT NULL AUTO_INCREMENT
  , type_code CHAR(1) NOT NULL
  , PRIMARY KEY (a_id)
  , UNIQUE KEY (type_code, a_id)
  , FOREIGN KEY (type_code)
      REFERENCES Type (type_code)
  ) ;

Las tablas de subtipos (que ahora hacen referencia a la combinación de la clave principal de A y type_code:

CREATE TABLE B
  ( a_id INT NOT NULL
  , type_code CHAR(1) NOT NULL DEFAULT 'B'
  , PRIMARY KEY (type_code, a_id)
  , FOREIGN KEY (type_code, a_id)
      REFERENCES A (type_code, a_id)
  , CHECK (type_code = 'B')
  ) ;

CREATE TABLE C
  ( a_id INT NOT NULL
  , type_code CHAR(1) NOT NULL DEFAULT 'C'
  , PRIMARY KEY (type_code, a_id)
  , FOREIGN KEY (type_code, a_id)
      REFERENCES A (type_code, a_id)
  , CHECK (type_code = 'C')
  ) ;

Lo anterior funcionaría bien, si solo MySQL hubiera implementado CHECK restricciones Pero no lo ha hecho. Entonces, para estar absolutamente seguro de que se cumplen todas sus especificaciones, y no 'B' los datos de tipo se insertan en C table, tendrá que agregar 2 tablas de "tipo" más (y eliminar las inútiles en MySQL CHECK restricciones):

CREATE TABLE TypeB
  ( type_code CHAR(1) NOT NULL
  , PRIMARY KEY (type_code)
  ) ;

CREATE TABLE TypeC
  ( type_code CHAR(1) NOT NULL
  , PRIMARY KEY (type_code)
  ) ;

con exactamente 1 fila cada uno:

INSERT INTO TypeB (type_code)
VALUES ('B') ;

INSERT INTO TypeC (type_code)
VALUES ('C') ;

y los FK adicionales:

ALTER TABLE B
  ADD FOREIGN KEY (type_code)
    REFERENCES TypeB (type_code) ;

ALTER TABLE C
  ADD FOREIGN KEY (type_code)
    REFERENCES TypeC (type_code) ;

Con estas restricciones, cada fila de la tabla A será de tipo B o C y estará en la tabla respectiva (B o C) y nunca en ambas.

Si también desea asegurarse de que estarán exactamente en una tabla (y nunca ni en B ni en C), debe tener cuidado al insertar en A (todas las inserciones deben realizarse con una transacción que cumpla ese requisito).