我有一个包含URL的表,其中一些URL超过255个字符。我想在URL列上强制使用唯一性约束,但MySQL不允许我在URL上创建密钥。我正在使用InnoDB / UTF8表。根据我的理解,每个字符使用多个字节,密钥限制为766个字节(在InnoDB中)。
根据网址保持行唯一的优雅方法是什么?
答案 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 ;