整个mysql表上的唯一键?

时间:2011-03-15 11:14:16

标签: mysql mysql-error-1054 unique-key

假设我有一个包含两列的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`)

感谢。

编辑:我可以使用以下触发器完成此操作:

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

但是,我没有看到“A OR B已存在”错误消息,但是:

  

ERROR 1054(42S22):'where子句'中的未知列'不存在'

再次感谢!

3 个答案:

答案 0 :(得分:2)

是的,这是可能的。

1种方式

如果已在其他列/表中找到该值,则需要创建BEFORE INSERT TRIGGER并返回错误。

从此blog post

  

MySQL触发器:如何使用a中止INSERT,UPDATE或DELETE   触发?在EfNet的#mysql上有人   问:

     

如果我的业务规则失败,如何触发操作会中止操作?

     

在MySQL 5.0和5.1中,您需要   采取一些技巧来制作一个   触发失败并提供有意义的   错误信息。 MySQL存储   程序FAQ说明错误   处理:

     

SP 11. SP是否有“提高”语句来“引发应用程序错误”?对不起,现在不行。 SQL标准SIGNAL和RESIGNAL语句位于TODO上。

     

也许MySQL 5.2将包含SIGNAL   这个hack的声明   直接从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 :(得分:1)

关键地执行此操作的正确(和简单)方法是创建两个表T1和T2,其中T2具有返回T1的外键关系(多对一)。唯一索引/约束在T2.yourUniqueColumn上声明,如果必须区分该列中的值,请将另一列添加到T2:

   T1
   id
   foo


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

你最初可以用这种方式填充T2(假设在T2中自动递增PK):

  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

根据经验法规,当您使用关系数据库时,无论何时您发现自己在执行程序事务,都应该退后一步并考虑重构。

答案 2 :(得分:0)

您可以使用COALESCE从A或B获取第一个空值,前提是不要设置http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce