确保MYSQL / InnoDB中varchar大于255的唯一性

时间:2011-11-23 01:47:36

标签: mysql innodb

我有一个包含URL的表,其中一些URL超过255个字符。我想在URL列上强制使用唯一性约束,但MySQL不允许我在URL上创建密钥。我正在使用InnoDB / UTF8表。根据我的理解,每个字符使用多个字节,密钥限制为766个字节(在InnoDB中)。

根据网址保持行唯一的优雅方法是什么?

3 个答案:

答案 0 :(得分:4)

对于MySQL 5.7或更高版本,请参阅Andre Dalcher's answer以获得使用生成列的更好方法。


您可以使用网址的SHA1 hash作为唯一键。两个网址有可能具有相同的哈希值,但其概率非常小,实际上这种方法应该可以正常工作。


您还可以设置触发器,以便在INSERT时自动计算hash列:

CREATE TRIGGER mytrigger
BEFORE INSERT
ON foo
FOR EACH ROW SET
    NEW.hash = SHA1(NEW.url)

答案 1 :(得分:2)

在MySQL 5.7.6或更高版本中,您可以使用包含要放置唯一性约束的列的哈希的generated column来执行此操作。

默认情况下,生成的列为VIRTUAL,这意味着值永远不会存储在磁盘上。虚拟列只能使用InnoDB引擎在MySQL> = 5.7.8版本中编制索引;对于MyISAM或旧版本的MySQL,您必须使用STORED列。

mysql> CREATE TABLE url_hash_test (
    ->   url TEXT,
    ->   url_hash VARCHAR(32) AS (md5(url)),
    ->   UNIQUE(url_hash)
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO url_hash_test SET url='http://example.com';
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO url_hash_test SET url='http://example.com';
ERROR 1062 (23000): Duplicate entry 'a9b9f04336ce0181a08e774e01113b31' for key 'url_hash'

答案 2 :(得分:0)

您可以将网址拆分为2个或更多列,并使组合(URLpart1, URLpart2, ..., URLpartN)唯一。然后,允许的最大索引长度将从767字节增加到3072字节。例如:

CREATE TABLE atest
( id INT NOT NULL AUTO_INCREMENT 
, a VARCHAR(255) NOT NULL
, b VARCHAR(255) NOT NULL DEFAULT ''
, c VARCHAR(255) NOT NULL DEFAULT ''
, d VARCHAR(255) NOT NULL DEFAULT ''
, PRIMARY KEY (id)
, UNIQUE INDEX url_idx (a,b,c,d)
) ENGINE = InnoDB ;