2011-03-15 12 views
6

Supongamos que tengo una tabla mysql con dos columnas: A y B. ¿Es posible tener una clave única para que solo pueda insertar un valor una sola vez en A o B (una vez en toda la tabla)?clave única en toda la tabla mysql?

Por lo tanto, si la columna A contiene 'qwe' y B contiene 'asd', estos dos valores ya no se pueden insertar en ninguna columna.

esto no funcionará:

UNIQUE KEY `A` (`A`,`B`), 
UNIQUE KEY `A_2` (`A`), 
UNIQUE KEY `B` (`B`), 
UNIQUE KEY `B_2` (`B`,`A`) 

gracias.

edición: yo era capaz de lograr esto con el siguiente trigger:

delimiter | 
create trigger unique_check before insert on mytable 
     for each row begin 
       declare alreadyexists integer; 
      select count(*) > 0 into alreadyexists from mytable 
       where A=NEW.B or B=NEW.A; 
      IF alreadyexists = 1 THEN begin 
      DECLARE dummy INT; 
     SELECT 'A OR B already exists' INTO dummy FROM mytable 
      WHERE nonexistent = 'value'; 
end; 
END IF; 
END;| 

Sin embargo, no veo la 'A o B ya existe' mensaje de error, pero:

ERROR 1054 (42S22): columna desconocida 'inexistente' en 'where clause'

¡Gracias nuevamente!

+0

Otra opción podría ser tener una tabla con las columnas 'value',' a', 'b' con' a' y 'b' como bits, y luego cuando el valor (que debe ser exclusivo) se ingrese también establece a o b en 1. Supongo que todavía da el problema de qué pasa si alguien pone en 1 para ambos 'a' y' b' pero esa es otra manera – Harold

Respuesta

2

Sí, es posible.

1 manera es

Es necesario crear un disparador BEFORE INSERT y error volver si el valor se encuentra ya en otras columnas/tablas.

De esta blog post

MySQL disparadores: ¿Cómo se cancela una INSERT, UPDATE o DELETE con un gatillo ? En EfNet #mysql alguien preguntó:

¿Cómo puedo hacer que un desencadenador anule la operación si falla mi regla de negocio?

En MySQL 5.0 y 5.1 que necesita para recurrir a algunos trucos para hacer un disparador fallar y entregar un mensaje de error significativa. El MySQL almacenados Procedimiento FAQ dice esto acerca de error de manipulación :

SP 11. ¿SP tiene un “subir” declaración “aumentar los errores de aplicación”? Lo siento, no en este momento. Las sentencias SIGNAL y RESIGNAL estándar de SQL están en TODO.

Quizás MySQL 5.2 incluirá SEÑAL declaración que hará que este truco robada directamente de MySQL Stored Procedimiento de programación obsoletos. ¿Qué es el truco? Va a forzar MySQL para intentar utilizar una columna que no existe. ¿Feo? Sí. ¿Funciona ? Por supuesto.

CREATE TRIGGER mytabletriggerexample 
BEFORE INSERT 
FOR EACH ROW BEGIN 
IF(NEW.important_value) < (fancy * dancy * calculation) THEN 
    DECLARE dummy INT; 

    SELECT Your meaningful error message goes here INTO dummy 
     FROM mytable 
     WHERE mytable.id=new.id 
END IF; END; 

Otra forma

También puede ver con Transactions

utilizar un procedimiento con la transacción para insertar datos en la tabla de transacciones (InnoDB),

En la escritura de gatillo en condición de error:

set @error=1; 

En el procedimiento algo como esto:

set @error=0; 
start transaction 
do insert 
if @error>0 then rollback; 
else commit; 
+0

gracias por su ayuda, intentaré esto! – atlau

1

La forma correcta (y simple) Hacer esto relacionalmente es crear dos tablas, T1 y T2, donde T2 tiene una relación de clave externa (muchos a uno) de vuelta a T1. El único índice/restricción se declaró en T2.yourUniqueColumn, y si es necesario diferenciar entre los valores de esa columna, añadir otra columna a T2:

T1 
    id 
    foo 


    T2 
    t2id 
    t1id fk references T1 
    yourUniqueColumn [unique index/constraint] 
    extraColumnToDescribeTheValueInUniqueColumn  

Se podría llenar inicialmente T2 de esta manera (se supone de incremento automático PK en T2):

insert into T2 
    (t1id, yourUniqueColumn, extraColumn) 
    select t1.id as t1id, T1.A as yourUniqueColumn, 'A' as extraColumn from T1 


    insert into T2 
    (t1id, yourUniqueColumn, extraColumn) 
    select T1.id as t1id, T1.B as yourUniqueColumn, 'B' as extraColumn from T1 

Como regla empírica, cada vez que usted se encuentra haciendo cosas procesalmente cuando se trabaja con una base de datos relacional, es el momento de dar un paso atrás y considerar refactorización.

Cuestiones relacionadas