我有一个主键为varchar(255)的表。在某些情况下,255个字符是不够的。我尝试将字段更改为文本,但我得到以下错误:

BLOB/TEXT column 'message_id' used in key specification without a key length

我该如何解决这个问题?

编辑:我还应该指出,这个表有一个多列的复合主键。


当前回答

我得到这个错误时,添加一个索引的文本类型列表。您需要声明每个文本类型要使用的大小。

将大小放入括号()内

如果使用了太多字节,您可以在方括号中为varchar声明一个大小,以减少用于索引的数量。即使你已经为varchar(1000)这样的类型声明了一个大小。您不需要像其他人所说的那样创建一个新表。

添加索引

alter table test add index index_name(col1(255),col2(255));

添加唯一索引

alter table test add unique index_name(col1(255),col2(255));

其他回答

The error happens because MySQL can index only the first N chars of a BLOB or TEXT column. So The error mainly happens when there is a field/column type of TEXT or BLOB or those belong to TEXT or BLOB types such as TINYBLOB, MEDIUMBLOB, LONGBLOB, TINYTEXT, MEDIUMTEXT, and LONGTEXT that you try to make a primary key or index. With full BLOB or TEXT without the length value, MySQL is unable to guarantee the uniqueness of the column as it’s of variable and dynamic size. So, when using BLOB or TEXT types as an index, the value of N must be supplied so that MySQL can determine the key length. However, MySQL doesn’t support a key length limit on TEXT or BLOB. TEXT(88) simply won’t work.

当您尝试将表列从非TEXT和非BLOB类型(如VARCHAR和ENUM)转换为TEXT或BLOB类型时,错误也会弹出,该列已经被定义为唯一约束或索引。Alter Table SQL命令将失败。

该问题的解决方案是从索引或唯一约束中删除TEXT或BLOB列,或将另一个字段设置为主键。如果您不能这样做,并希望对TEXT或BLOB列进行限制,请尝试使用VARCHAR类型并对其进行长度限制。默认情况下,VARCHAR被限制为255个字符,它的限制必须在声明后的括号内隐式指定,即VARCHAR(200)将限制为仅200个字符长。

Sometimes, even though you don’t use TEXT or BLOB related type in your table, the Error 1170 may also appear. It happens in a situation such as when you specify VARCHAR column as primary key, but wrongly set its length or characters size. VARCHAR can only accepts up to 256 characters, so anything such as VARCHAR(512) will force MySQL to auto-convert the VARCHAR(512) to a SMALLTEXT datatype, which subsequently fails with error 1170 on key length if the column is used as primary key or unique or non-unique index. To solve this problem, specify a figure less than 256 as the size for VARCHAR field.

MySQL错误1170(42000):在键规范中使用的BLOB/TEXT列没有键长度

我得到这个错误时,添加一个索引的文本类型列表。您需要声明每个文本类型要使用的大小。

将大小放入括号()内

如果使用了太多字节,您可以在方括号中为varchar声明一个大小,以减少用于索引的数量。即使你已经为varchar(1000)这样的类型声明了一个大小。您不需要像其他人所说的那样创建一个新表。

添加索引

alter table test add index index_name(col1(255),col2(255));

添加唯一索引

alter table test add unique index_name(col1(255),col2(255));

另一种很好的处理方法是创建没有唯一约束的TEXT字段,并添加一个兄弟VARCHAR字段,该字段是唯一的,并且包含TEXT字段的摘要(MD5、SHA1等)。当您插入或更新TEXT字段时,计算并存储整个TEXT字段的摘要,这样您就可以对整个TEXT字段(而不是一些前面的部分)有一个可以快速搜索的唯一性约束。

我曾经用过这个,也犯过你提到的错误:

CREATE INDEX idx_col1 ON my_table (col1);

然后我把它换成了这个,并解决了:

CREATE INDEX idx_col1 ON my_table (col1(255));

您应该定义要索引TEXT列的哪个前导部分。

InnoDB对每个索引键有768字节的限制,你不能创建一个超过这个长度的索引。

这将很好地工作:

CREATE TABLE t_length (
      mydata TEXT NOT NULL,
      KEY ix_length_mydata (mydata(255)))
    ENGINE=InnoDB;

注意,键大小的最大值取决于列字符集。像LATIN1这样的单字节字符集有767个字符,而UTF8只有255个字符(MySQL只使用BMP,每个字符最多需要3个字节)

如果您需要整个列都是主键,计算SHA1或MD5哈希并将其用作主键。