sql >> Databasteknik >  >> RDS >> Mysql

MySQL Cross Table Constraint

Du kan använda en "typ"-tabell:

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

med exakt 2 rader (lika många som de olika undertypstabellerna du behöver:

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

Supertyptabellen (som innehåller en kolumn som refererar till "Typ"):

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)
  ) ;

Undertypstabellerna (som nu refererar till kombinationen av A:s primärnyckel och typ_kod:

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')
  ) ;

Ovanstående skulle fungera bra, om bara MySQL hade implementerat CHECK begränsningar. Men det har det inte gjort. Så för att vara helt säker på att alla dina specifikationer upprätthålls, och inte 'B' typdata infogas i C tabell, måste du lägga till ytterligare två "typ"-tabeller (och ta bort de värdelösa i MySQL CHECK begränsningar):

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)
  ) ;

med exakt 1 rad vardera:

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

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

och de ytterligare FK:erna:

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

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

Med dessa begränsningar kommer varje rad i tabell A att vara antingen av typ B eller C och den kommer att finnas i respektive tabell (B eller C) och aldrig i båda.

Om du också vill säkerställa att de kommer att finnas i exakt en tabell (och aldrig i varken B eller C), bör du vara försiktig när du infogar i A (alla insättningar ska göras med en transaktion som upprätthåller det kravet).




  1. Indexstorlekar i MySQL

  2. postgreSQL funktionsanropspaket

  3. Hur fungerar avstängning av transaktioner under våren?

  4. Knepig SQL-sats över 3 tabeller