2012-09-12 23 views
1

我有一个包含用户元数据的表。有4个字段...只有当另一个键包含特定值时,MySQL唯一键

`ID`,`meta_name`,`meta_value`,`user_id` 

我想在此表中存储电子邮件。自然,这些必须是独一无二的。不过,我想将其他数据存储在此表中,其中数据不需要是唯一的。有没有什么办法可以将'meta_value'限制为唯一,只有'meta_name'等于'email'?

+0

直接?你必须创建一个存储过程来添加到这个表中,当meta_name是电子邮件时,你执行表锁,检查电子邮件然后解锁表 – Hawili

+1

不,这正是不使用这种设计的原因。如果'meta_name'可能值的数量很小,则将它们定义为列(然后放置一个约束将很简单);否则请考虑将它们存储在不同的表中。 – raina77ow

回答

4

通过MySQL的约束 - 没有。

但是,您可以使用插入/更新触发器来验证数据的唯一性并禁止非法操作。

这里是INSERT触发器的草案(你可以在这里发挥它:http://sqlfiddle.com/#!2/5c9e3):

DELIMITER // 

CREATE TRIGGER VerifyInsert BEFORE INSERT ON YourTestTable 
FOR EACH ROW 
BEGIN 

IF (SELECT COUNT(1) FROM YourTestTable 
WHERE YourTestTable.meta_name = 'EMail' AND YourTestTable.meta_value = NEW.meta_value 
AND NEW.meta_name = YourTestTable.meta_name) > 0 THEN 

    SIGNAL SQLSTATE '45001' SET MESSAGE_TEXT = 'VerifyInsertFailed'; 

END IF; 


END; 

// 
+0

库巴,可以添加独特的约束,以满足我上面概述的要求? (独特取决于另一个关键) – Shane

+0

不,如我所说:“通过MySQL的约束 - 不”。 –

+0

对不起,我自己在阅读你的回复 - 我的意思是更新触发器,而不是唯一的限制。 – Shane

2

随着MySQL的约束上这是不可能的,没有特别的技巧(如冗余列unique_helpermeta_name = email恒定值并且对于每个其他+ UNIQUE索引为unique_helper + meta_value)。

但是你可以在InnoDB表使用自定义触发:(rememeber把yourTable名)从数据库

CREATE TRIGGER triggerName 
BEFORE INSERT ON yourTable 
FOR EACH ROW 
BEGIN 
    IF NEW.meta_name = 'email' AND EXISTS (SELECT 1 FROM yourTable WHERE meta_name='email' AND meta_value=NEW.meta_value) 
    THEN 
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Duplicate email'; 
    END IF; 
END; 
+0

感谢rogal111,我还没有听说过SIGNAL - 我会研究它。 – Shane

相关问题