假设我有一个包含两列的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子句'中的未知列'不存在'
再次感谢!
答案 0 :(得分:2)
是的,这是可能的。
1种方式
如果已在其他列/表中找到该值,则需要创建BEFORE INSERT
TRIGGER并返回错误。
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