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

Pregunta de diseño de base de datos sobre claves foráneas anulables y normalización

Algunos muy buenos diseñadores usan NULL en claves foráneas sin consecuencias adversas. Yo mismo me inclino de esa manera. Un FK anulable representa una relación opcional. En los casos en que la entidad no tiene relación, el FK contiene un NULL. El espacio de arriba es mínimo. Cuando se realizan combinaciones (equicombinaciones, más precisamente) en las dos tablas, las instancias que contienen NULL en el FK se eliminarán de la combinación, y eso es apropiado.

Habiendo dicho eso, voy a recomendarte un cuarto método. Esto implica un total de 4 tablas, cuentas, widgets, tipos y tipos_personalizados. La tabla custom_types utiliza una técnica llamada Shared-primary-key, que se describe a continuación.

CREATE TABLE accounts (
    account_id  INT UNSIGNED AUTO_INCREMENT NOT NULL, 
    # Other Columns...,
    PRIMARY KEY (account_id)
    );  
CREATE TABLE widgets (
    widget_id   INT UNSIGNED AUTO_INCREMENT NOT NULL,
    account_id  INT UNSIGNED NOT NULL, 
    type_id     INT UNSIGNED NOT NULL,
    PRIMARY KEY (widget_id),
    FOREIGN KEY (account_id) REFERENCES accounts(account_id) ON DELETE CASCADE,
    FOREIGN KEY (type_id) REFERENCES types(type_id)
    );  
CREATE TABLE types (
    type_id     INT UNSIGNED AUTO_INCREMENT NOT NULL,
    account_id  INT UNSIGNED NOT NULL, 
    name        VARCHAR(100) NOT NULL,
    PRIMARY KEY (type_id),
    FOREIGN KEY (account_id) REFERENCES accounts(account_id)
CREATE TABLE custom_types (
    type_id     INT NOT NULL,
    account_id  INT UNSIGNED NOT NULL, 
    PRIMARY KEY (type_id),
    FOREIGN KEY (type_id) REFERENCES types(type_id),
    FOREIGN KEY (account_id) REFERENCES accounts(account_id)

);

La columna type_id en custom_types es una clave principal compartida. Tenga en cuenta que se declara AMBOS como clave principal y como clave externa, y que no utiliza numeración automática. Es una copia de la clave principal en tipos para la entrada correspondiente. La tabla de tipos personalizados contiene todos los datos que están presentes en los tipos personalizados pero ausentes en los tipos preestablecidos.

Para los tipos preestablecidos, se realiza una entrada en tipos, pero no se realiza ninguna entrada en tipos_personalizados. Para custom_types, primero se realiza una entrada en tipos y luego el valor resultante de type_id se copia en custom_types, junto con account_id.

Si utiliza tipos INNER JOIN y custom_types, los tipos preestablecidos se eliminan de la unión. Si desea tipos personalizados y preestablecidos en una sola unión, debe usar LEFT JOIN o RIGHT JOIN para obtener ese efecto. Tenga en cuenta que el resultado de LEFT o RIGHT JOIN contendrá algunos NULL, aunque esos NULL no estén almacenados en la base de datos.

Al hacer clic en esta le dará una descripción más detallada de la técnica de clave primaria compartida.