Уникальный ключ на всю таблицу MySQL? - PullRequest
6 голосов
/ 15 марта 2011

Предположим, у меня есть таблица mysql с двумя столбцами: A и B. Можно ли иметь уникальный ключ, чтобы я мог вставить значение только один раз в A или B (один раз во всей таблице)?

Таким образом, если столбец A содержит «qwe», а B содержит «asd», эти два значения больше не могут быть вставлены ни в один из столбцов.

это не будет работать:

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

спасибо.

edit: мне удалось сделать это с помощью следующего триггера:

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

Однако я не вижу сообщения об ошибке «А ИЛИ B уже существует», а:

ОШИБКА 1054 (42S22): неизвестный столбец «отсутствует» в «предложении where»

Еще раз спасибо!

Ответы [ 3 ]

2 голосов
/ 15 марта 2011

Да, это возможно.

1 - это

Вам необходимо создать BEFORE INSERT TRIGGER и вернуть ошибку, если значение уже найдено в других столбцах /таблицы.

Из этого сообщения в блоге

Триггеры MySQL: как прервать операцию INSERT, UPDATE или DELETE с помощью триггера?На #mysql в EfNet кто-то спросил:

Как сделать триггер, прервавший операцию, если мое бизнес-правило не выполняется?

В MySQL 5.0 и 5.1 вам нужно прибегнуть кнекоторые хитрости, чтобы триггер не срабатывал и доставлял значимое сообщение об ошибке.Часто задаваемые вопросы о хранимых процедурах MySQL говорят об обработке ошибок:

SP 11. Есть ли у операторов SP выражение «поднять», чтобы «вызвать ошибки приложения»?Извините, не в настоящее время.Стандартные операторы SQL SIGNAL и RESIGNAL находятся в TODO.

Возможно, MySQL 5.2 будет включать в себя оператор SIGNAL, который сделает этот хак украденным прямо из программирования хранимых процедур MySQL.Что за хак?Вы собираетесь заставить MySQL пытаться использовать столбец, который не существует.Гадкий?Да.Это работает?Конечно.

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;

Другой способ

Вы также можете сделать с Transactions

использовать процедуру с транзакцией для вставки данныхв транзакционную таблицу (InnoDB)

В триггере запишите условие ошибки:

set @error=1; 

В процедуре примерно так:

set @error=0; 
start transaction 
do insert 
if @error>0 then rollback; 
else commit; 
1 голос
/ 15 марта 2011

Правильный (и простой) способ сделать это реляционно - создать две таблицы, T1 и T2, где T2 имеет отношение внешнего ключа (много-к-одному) обратно к T1.Уникальный индекс / ограничение объявляется в T2.yourUniqueColumn, и если вам необходимо различать значения в этом столбце, добавьте еще один столбец в T2:

   T1
   id
   foo


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

Вы можете изначально заполнить T2 таким образом (предполагается, что-инкрементный PK в 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

Как правило, всякий раз, когда вы обнаруживаете, что делаете процедурно при работе с реляционной базой данных, самое время сделать шагназад и рассмотрим рефакторинг.

0 голосов
/ 15 марта 2011

Вы можете использовать COALESCE, чтобы получить первое нулевое значение от A или B, при условии, что оба не установлены http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce

...