2011-03-15 60 views
6

假设我有一个包含两列的mysql表:A和B.是否可以有一个唯一键,这样我只能在A或B(一次在整个表中)中只插入一次值?整个mysql表的唯一键?

因此,如果列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或B已经存在' 错误消息,但:

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

再次感谢!

+0

另一种选择可能是使用一个带'a'和'b'位的列'value','a','b'的表格,然后当值(必须是唯一的)被输入时也设置a或b为1.我想这仍然给出了如果某人为'a'和'b'放入1的问题,但这是另一种方式 – Harold 2011-03-15 11:21:45

回答

2

是的,这是可能的。

1的方式是

你需要创建一个BEFORE INSERT TRIGGER,如果该值在其他列/表已经找到返回错误。

从这个blog post

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

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

在MySQL 5.0和5.1,你需要 诉诸一些挂羊头卖狗肉,以使 触发失败,并提供一个有意义的 错误消息。 MySQL存储 过程常见问题解答关于错误 处理:

SP 11. SP是否有“raise”语句来“引发应用程序错误”?对不起,目前没有。 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; 
+0

感谢您的帮助,我会试试这个! – atlau 2011-03-15 11:28:31

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 

作为一个规则的拇指,无论何时你发现自己做与关系数据库时在程序上的东西,是时候退一步,考虑重构。