2009-01-09 12 views
14

Estoy tratando de crear una relación donde se puede incluir cualquiera de las cuatro partes diferentes, pero cualquier colección de las mismas partes debe tratarse como única.Pregunta de MySQL - Clave única ¿No funciona correctamente o no entiendo bien?

Ejemplo: Una asignación debe tener una empresa asignada, opcionalmente puede tener una ubicación asignada, grupo de trabajo y programa. Una tarea puede no tener un grupo de trabajo sin una ubicación.

Supongamos que tenemos las compañías A, B, C; ubicaciones X, Y, Z; grupos de trabajo I, J, K y los programas 1, 2, 3.

Así relaciones válidas podrían incluir A - X - I - 1 A - Z - 2 B - Y C C - 3 B - Z - K

Pero las relaciones no válidos incluiría a - K (Grupo de trabajo sin la localización) Y - K - 1 (Ninguna empresa)

Por lo tanto, para crear mi mesa, he creado

companyID INT NOT NULL, 
FOREIGN KEY companyKEY (companyID) REFERENCES company (companyID), 
locationID INT, 
FOREIGN KEY locationKEY (locationID) REFERENCES location (locationID), 
workgroupID INT, 
FOREIGN KEY workgroupKEY (workgroupID) REFERENCES workgroup (workgroupID), 
programID INT, 
FOREIGN KEY programKEY (programID) REFERENCES program (programID), 
UNIQUE KEY companyLocationWorkgroupProgramKEY (companyID, locationID, workgroupID, programID) 

Calculo esto sería manejar todas mis relaciones, además de la neccessity de una asignación a tener una ubicación si hay un grupo de trabajo (que yo puedo hacer feliz mediante programación o con disparadores, creo)

Sin embargo, cuando pruebo este esquema, me permite ingresar lo siguiente ...

INSERT INTO test VALUES (1, null, null, null), (1, null, null, null); 

... sin queja. Supongo que (1, nulo, nulo, nulo) no se iguala porque se incluyen valores nulos. Si este es el caso, ¿hay alguna forma de que pueda manejar esta relación?

¡Cualquier ayuda sería apreciada!

Respuesta

17

Esta es una función (aunque tampoco es lo que esperaba).

This thread sugiere hacer su clave una clave primaria para obtener el comportamiento que se esperaba:

Esta es una característica - un valor NULL es un valor indefinido , por lo tanto, dos valores NULL no son los mismos. Puede ser un poco confuso pero tiene sentido cuando lo pienses al .

Un índice UNIQUE garantiza que los valores no nulos de son únicos; puede especificar que su columna no acepte valores NULL.

+0

Configurar las columnas para que sean "NOT NULL" funcionaría, pero también requeriría la adición de elementos de datos como Rob y sugerí que permitieran que la base de datos coincidiera correctamente con los requisitos enumerados; si NULL no está permitido, necesita un El valor "NO FOO" es una entrada válida en la tabla FOO a la que se refiere el FK. –

+1

En cuanto a hacer que el índice sea su clave principal: el único problema es que no puede crear una columna AUTO_INCREMENT a menos que sea parte de la clave principal. Ese es el problema que estoy teniendo. –

+0

Otro problema para hacer que las columnas NULL'able sean parte de la PK es que pasan a ser NOT NULL y en su lugar obtienes 0 o una cadena vacía como valor predeterminado. – Rafa

3

La única manera que puedo pensar de manejar esto sin gatillos adicionales/programación sería tener una sola "ninguna de las anteriores" valor en cada una de las tablas de referencia, por lo que la prueba se vería así

INSERT INTO test VALUES (1, NO_LOCATION, NO_WORKGROUP, NO_PROGRAM), 
         (1, NO_LOCATION, NO_WORKGROUP, NO_PROGRAM) 

Donde los identificadores NO_* son del tipo/longitud adecuados para sus columnas de ID. Esto luego fallaría, como es de esperar.

0

En MySQL NULL! = NULL, o lo que sea.Entonces eso es lo que el UNIQUE no funciona. Debe usar otro valor predeterminado para los espacios en blanco, como cero

0

Creo que es importante tener en cuenta que existe una forma adecuada para interpretar y manejar los valores NULL, y el comportamiento exhibido por el OP es exactamente lo que se pretende. Puede ignorar ese comportamiento, y puede manejar su consulta de la forma que desee sin objeciones por mi parte, pero podría ser "Aceptar" una respuesta que describa alguna forma de Mejores Prácticas, en lugar de una preferencia personal no estándar.

O si no está de acuerdo con las mejores prácticas de consenso, simplemente no puede aceptar ninguna respuesta.

No es una carrera para obtener una respuesta aceptada lo más rápido posible. La deliberación y la colaboración también pretenden ser parte del proceso, creo.

Cuestiones relacionadas