2010-02-18 16 views
5

Tengo las siguientes tablas en el servidor MySQL:Cómo hacer cumplir únicos de varias tablas

Companies: 
- UID (unique) 
- NAME 
- other relevant data 

Offices: 
- UID (unique) 
- CompanyID 
- ExternalID 
- other data 

Employees: 
- UID (unique) 
- OfficeID 
- ExternalID 
- other data 

En cada uno de ellos es el UID identificador único, creado por la base de datos.

Hay claves externas para asegurar los enlaces entre Empleado -> Oficina -> Compañía en el UID.

Los campos ExternalID en Oficinas y Empleados es el ID proporcionado a mi aplicación por la Compañía (mi cliente (s) en realidad). Los clientes no tienen (y no les importa) mis propios ID, y todos los datos que mi aplicación recibe de ellos se identifican únicamente en función de sus ID (es decir, ExternalID en mis tablas).

I.e. una solicitud del cliente en pseudo-lenguaje es como "Soy empresa X, actualizar los datos para mi empleado Y".

Necesito forzar la exclusividad en la combinación de CompanyID y Employees.ExternalID, por lo que en mi base de datos no habrá duplicados de ExternalID para los empleados de la misma empresa.

Estaba pensando en 3 soluciones posibles:

  1. cambiar el esquema para que los empleados incluyen CompanyID, y crear restricción único en los dos campos.

  2. Aplicar un disparador, que al actualizar/insertar en Empleados valida la exclusividad.

  3. Haga cumplir la verificación del nivel de aplicación (es decir, mi servicio de recepción).

Mi alternativa dbadmin-en-me EFS que (3) es la peor solución, ya que no protege la base de datos de inconsistencia en caso de fallo en la aplicación o alguna otra cosa, y muy probablemente será el más lento uno.

La solución desencadenante puede ser lo que quiero, pero puede ser complicado, especialmente si se deben realizar varias inserciones/actualizaciones en una sola declaración, y no estoy seguro del rendimiento frente a (1).

Y (1) parece el enfoque más rápido y más fácil, pero va en contra de mi comprensión del modelo relacional.

Lo que opinan los expertos de SO DB son los pros y los contras de cada uno de los enfoques, especialmente si existe la posibilidad de agregar un nivel adicional de direccionamiento indirecto - es decir, Empresa -> Oficina -> Departamento -> Empleado, y la misma singularidad necesita ser preservado (Compañía/Empleado).

Respuesta

3

Tienes razón - # 1 es la mejor opción.
Por supuesto, me lo cuestionaría a primera vista (debido a acortando) pero sabiendo la regla de negocio para asegurar un empleado sólo está relacionado con una compañía - que tiene sentido.

Además, tendría una clave externa en relación al CompanyID en la tabla de empleados a la CompanyID en la mesa de oficina. De lo contrario, permite que un empleado se relacione con una empresa sin una oficina. A menos que sea aceptable ...

desencadenantes son el último recurso si la relación no puede ser demostrada en el modelo de datos, y el servicio de la lógica de la aplicación significa la lógica es centralizado - no hay oportunidad para que los datos erróneos que se produzca, a menos que alguien suelte restricciones (lo que significa que tienes problemas mayores).

+0

@OMG: Sí, las claves externas son claves foráneas. No los agregué en la Q por simplicidad. Gracias de todos modos por descubrir esto. Voy a editar la Q. –

0

Establezca auto_increment_increment al número de tabla que tiene. SET auto_increment_increment = 3; (es posible que desee configurar esto en su mi.CNF)

Entonces ajustar manualmente el valor AUTO_INCREMENT de partida de cada tabla para diferentes valores primera tabla para 1, segunda mesa para 2, tercera tabla para 3

Tabla 1 tendrá valores como 1,4,7, 10,13, etc

Tabla 2 tendrá valores como 2,5,8,11,14, etc

Tabla 3 tendrán valores como 3,6,9,12,15, etc

Por supuesto, esta es solo UNA opción, personalmente solo la convertiría en un valor combinado mi. Podría ser tan simple como TableID, AutoincrementID, donde el TableID es constante en todas las filas.

+0

Este fallará espectacularmente cuando se agrega una cuarta mesa. –

+0

Interesante idea. Entonces, ¿cómo exactamente hago cumplir la singularidad de la combinación Company + Employee.ExternalID? –

+1

En la reflexión, mi idea era estúpida, aunque una forma interesante de crear ideas únicas es a través de una tabla de entradas. http://code.flickr.com/blog/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/ – MindStalker

1

Cada una de las tablas provistas por la compañía debería incluir CompanyID en el `UNIQUE KEY' sobre los identificadores proporcionado por la empresa.

Compañía proporcionado por la integridad de referencia deben utilizar los identificadores proporcionado por la empresa:

CREATE TABLE company (
     uid INT NOT NULL PRIMARY KEY, 
     name TEXT 
     ); 

CREATE TABLE office (
     uid INT NOT NULL PRIMARY KEY, 
     companyID INT NOT NULL, 
     externalID INT NOT NULL, 
     UNIQIE KEY (companyID, externalID), 
     FOREIGN KEY (companyID) REFERENCES company (uid) 
     ); 

CREATE TABLE employee (
     uid INT NOT NULL PRIMARY KEY, 
     companyID INT NOT NULL, 
     officeID INT NOT NULL, 
     externalID INT NOT NULL, 
     UNIQIE KEY (companyID, externalID), 
     FOREIGN KEY (companyID) REFERENCES company(uid) 
     FOREIGN KEY (companyID, officeID) REFERENCES office (companyID, externalID) 
     ); 

etc.

+0

Gracias por la respuesta, así que la opción uno sobre la marcha. –

Cuestiones relacionadas