Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Restrição de tabela cruzada do MySQL


Você pode usar uma tabela "tipo":
CREATE TABLE Type
  ( type_code CHAR(1) NOT NULL
  , PRIMARY KEY (type_code)
  ) ;

com exatamente 2 linhas (tantas quantas as diferentes tabelas de subtipos que você precisa:
INSERT INTO Type (type_code)
VALUES ('B'), ('C') ;

A tabela de supertipos (que inclui uma coluna que faz referência 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)
  ) ;

As tabelas de subtipos (que agora estão referenciando a combinação da chave primária de A e 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')
  ) ;

O acima funcionaria bem, se apenas o MySQL tivesse implementado CHECK restrições. Mas não tem. Portanto, para ter certeza absoluta de que todas as suas especificações são aplicadas, e não 'B' tipo de dados é inserido em C table, você terá que adicionar mais 2 tabelas "type" (e remover o inútil no MySQL CHECK restrições):
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)
  ) ;

com exatamente 1 linha cada:
INSERT INTO TypeB (type_code)
VALUES ('B') ;

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

e os FKs adicionais:
ALTER TABLE B
  ADD FOREIGN KEY (type_code)
    REFERENCES TypeB (type_code) ;

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

Com essas restrições, cada linha da tabela A, será do tipo B ou C e estará na respectiva tabela (B ou C) e nunca em ambas.

Se você também quiser garantir que eles estarão em exatamente uma tabela (e nunca em B nem C), isso deve ser cuidado ao inserir em A (todas as inserções devem ser feitas com uma transação que reforce esse requisito).