6

假设我有一个包含两列的 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 已存在”错误消息,但是:

错误 1054 (42S22):“where 子句”中的未知列“不存在”

再次感谢!

4

3 回答 3

2

是的,这是可能的。

1方式是

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

从这篇博文

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

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

在 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; 
于 2011-03-15T11:18:48.663 回答
1

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

   T1
   id
   foo


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

您最初可以以这种方式填充 T2(假设在 T2 中自动增加 P​​K):

  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

根据经验,每当您发现自己在使用关系数据库时按程序执行操作,就该退后一步考虑重构了。

于 2011-03-15T11:37:01.880 回答
0

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

于 2011-03-15T11:29:04.890 回答