2016-05-29 253 views
1

我有一个很长的数据库字段(2083个字符),因此我无法在MySQL中为它设置UNIQUE约束。为MySQL数据库中的long varchar字段强制使用唯一值

我试过修改存储过程,所以我可以检查试图插入的值是否是唯一的,如果不是,则停止插入。但是,存储过程总是错误。我已经尝试了很多不同的语法。这真是奇怪,存储过程很好,只有if语句或插入,但不与两者。

感谢任何帮助。

BEGIN 
SET @insertedid := 0; 
SET @alreadyfound := 0; 
SELECT COUNT(lref_id) FROM listing_referrers WHERE lref_referring_url=in_lref_referring_url INTO @alreadyfound; 

IF (@alreadyfound = 0) THEN 
BEGIN 
    INSERT INTO listing_referrers (lref_listing_id,lref_referring_url,lref_createdby_userid,lref_created) VALUES (in_lref_listing_id, in_lref_referring_url, in_lref_createdby_userid, in_lref_created); 
    SET @insertedid = last_insert_id(); 
END 
SELECT @insertedid; 
END 

回答

1

想法使用触发器

我不会在这里使用的方法,但更喜欢使用触发ON INSERT。您可以在How to prevent using digits in a VARCHAR column using mysql?找到我的答案,它主要将CREATE TRIGGER的想法与SIGNAL的想法相结合,以防万一检测到错误情况。

所以,你的情况可能然而像

DELIMITER // 

CREATE TRIGGER trg_listing_referrers_unit_ins before insert on listing_referrers 
for each row 
begin 
    IF EXISTS (SELECT * FROM listing_referrers WHERE lref_referring_url = new.lref_referring_url) 
     THEN signal sqlstate '45000' set message_text = 'trying to insert duplicate lref_referring_url'; 
    END IF; 
END 
// 

DELIMITER ; 

注意的是,这需要MySQL 5.5或更高版本。如果你有一个早期版本的MySQL正在运行,这可能会变得很难看......

注意:根据你的表的大小listing_referrers在触发器中的SELECT声明可能会变成性能猪。请确保,即使您不能在lref_referring_url上定义具有NON-UNIQUE索引的UNIQUE索引。否则,你最终会得到一个O(n)算法,而不是O(log n)算法,这可能会产生巨大的差异。

想法使用散列键列

相反跟踪唯一在整个VARCHAR,你也可以检查你的真实密钥的哈希值的唯一性。例如,你可以在你的表中添加另一个名为key_hash的列,在其中输入一个UNIQUE KEY约束(如果你愿意的话,你甚至可以把它作为主键)。

插入时,你让MySQL的计算它的SHA2哈希值上的苍蝇,像

INSERT INTO listing_referrers (lref_referring_url, key_hash) 
    VALUES("http://server.bogus/mylong/url", SHA2("http://server.bogus/mylong/url", 256)); 

如果你输入相同的URL两次,其SHA2值将是相同的,因此唯一关键词key_hash的约束将开始反叛。

由于该函数的密码验证属性collision resistance,所以确保实际上不可能找到两个具有相同散列值的URL。如果您遇到问题,请将其发送至cryptographers community - 他们非常希望了解您的情况(以及许多情报服务)。

注意:如果记录的URL更改(通过UPDATE),您总是需要确保hash_key也相应更新。否则,你会发疯。如果这对你来说是一个真正的用例,你可能还想看看MySQL: Computed Column(我不知道,如果这也适用于主键列)。

想法限制了字符的唯一性

的如果能够限制唯一性第一n字符(含n < 255),那么你可能会发现Storing email VARCHAR(320) as UNIQUE, #1071 - Specified key was too long; max key length is 767有趣。

与限制3072个字符

如果你能确保你的网址将不超过3072个字符,改变字符集来ASCII会增加这个边界

想法(相比,UTF-8字符256)3072详细描述在MySQL unique 1500 varchar field error (#1071 - Specified key was too long)

+0

我会在触发部分使用'IF EXISTS(SELECT ...)THEN ...'。 –

+0

@PaulSpiegel请随时调整我的答案 - 我已经把它作为一个社区wiki条目,所以你应该被允许改变它。 – EagleRainbow

+0

哇,非常感谢你的全面回答。哈希键列可能最吸引我。如此优雅简单!我会运行一些测试,并让你知道我如何继续。 – ChrisFNZ

相关问题