操作MySQL出错提示“BLOB/TEXT column used in key specification without a key length”解决办法

本文详细解析了在MySQL数据库操作中常见的错误1170,即BLOB/TEXT字段在键规范中未指定键长度的问题。文章阐述了错误出现的原因,包括在创建或修改表时对BLOB/TEXT字段的不当使用,以及在将DataFrame数据保存至MySQL时的常见陷阱。提供了几种解决方案,如移除unique限制、改变字段类型为VARCHAR并设置长度,以及如何正确地将DataFrame数据转换为适合MySQL的格式。

[ERR] 12> 1170 - BLOB/TEXT column 'TABLE_OBJID' used in key specification without a key length

mysql出错提示“BLOB/TEXT column used in key specification without a key length”解决办法

一、问题

pandas对象将DataFrame数据保存到mysql中时,出现错误提示:
  BLOB/TEXT column used in key specification without a key length

或者

     在MySQL数据库中,当MySQL创建新表或者更改已存在表,这个表存在主键,并且是unique唯一性约束和索引约束时,或者是在定义一个索引来更改数据表的text字段操作语句的时候,下面的错误信息很可能会出现,并且经过当前操作命令的完成。错误信息为BLOB或者TEXT字段使用了未指定键值长度的键,发生了这样的错误:BLOB/TEXT column 'name' used in key specification without a key length。

       查阅资料后才知道,原来Mysql数据库对于BLOB/TEXT这样类型的数据结构只能索引前N个字符。所以这样的数据类型不能作为主键,也不能是UNIQUE的。所以要换成VARCHAR,但是VARCHAR类型的大小也不能大于255,当VARCHAR类型的字段大小如果大于255的时候也会转换成小的TEXT来处理。所以也同样有问题。

       此外,因为MySQL只能将BLOB/TEXT类型字段设置索引为BLOB/TEXT数据的钱N个字符,因此错误常常发生在字段被定义为TEXT/BLOB类型或者和TEXT/BLOB同质的数据类型,如TINYTEXT,MEDIUMTEXT,LONGTEXT ,TINYBLOB,MEDIUMBLOB 和LONGBLOB,并且当前操作是将这个字段设置成主键或者是索引的操作。在未指定TEXT/BLOB‘键长’的情况下,字段是变动的并且是动态的大小所以MySQL不能够保证字段的唯一性。因此当使用TEXT/BLOB类型字段做为索引时,N的值必须提供出来才可以让MySQL决定键长,但是MySQL不支持在TEXT/BLOB限制,TEXT(88)是不行的。

     当你试图将数据表中的一个非TEXT或者非BLOB类型如VARCHAR或ENUM的字段转换成TEXT/BLOB,同时这个字段已经被定义了unique限制或者是索引,这个错误也会弹出,并且更改数据表的命令会执行失败

二、原因

出问题的原因是DataFrame对象索引的数据类型是TEXT/BLOB或其从属的类型,当将其作为mysql中的主键的时候,如果这些数据类型缺少明确的长度值,mysql无法保证主键的唯一性,因为这个主键是一个变量,其长度是动态的。所以当使用 TEXT/BLOB类型的数据作为索引的时候,数据的长度必须提供给mysql,使其能够明确键的长度。但是mysql不支持对TEXT/BLOB长度的限制。

同样的错误也会出现在试图将非TEXT/BLOB类型的数据列转换成TEXT/BLOB类型,这些列被定义成独立的索引。AlterTable命令会失效。

三、解决方法

       解决方案是将unique限制和索引从TEXT/BLOB字段中移除,或者是设置另一个字段为主键。如果不得不设置成主键,而想限制TEXT/BLOB的长度,可以尝试使用VARCHAR并设置其长度。VARCHAR默认长度是255个字符,并且其长度必须在其声明之后的右边括号中设置,例如,VARCHAR(200)将其设置成200个字符长度。

       有时候,即使你在数据表中不使用TEXT/BLOB类型或者同质类型,error1170 也会出现,这个问题出现在当你设置一个VARCHAR字段为主键,但是却错误的设置了长度或者字符数,事实上,VARCHAR只能接受最大为256个字符串,但是你错误的设置成VARCHAR(512)等一些错误的设置,这些错误的设置会强制MySQL自动将VARCHAR(512)等转换成SMALLINT类型,同时这个字段被设置成primary key ,unique限制或者index索引等,然后执行操作就出现error 1170错误,解决问题的方法,为VARCHAR域指定小于256的长度。

mysql #1170错误(42000) BLOB/TEXT Column Used in Key Specification Without a Key Length

将DataFrame数据输出到mysql时强制将索引转换成VARCHAR并限制其长度,其中的code是索引的标签:

1 data.to_sql('data',engine,if_exists='replace',dtype={'code':VARCHAR(data.index.get_level_values('code').str.len().max())})

参考:https://www.cnblogs.com/zhangjpn/p/6133793.html 

           https://blog.youkuaiyun.com/u012069924/article/details/28858337

<think> 我们正在解决MySQL中出现的错误:BLOB/TEXT列'cInvCode'在键规范中使用但没有键长度的问题。 根据引用[3]:出现类似错误("BLOB/TEXT column 'code' used in key specification without a key length")是因为在创建索引时,对BLOBTEXT类型的列使用了索引但没有指定键的长度。这是因为MySQL不允许对BLOBTEXT类型的列直接创建索引(除非指定前缀长度)。 解决方法: 1. 修改索引:在创建索引时,为BLOBTEXT列指定一个前缀长度(即只对该列的前若干个字符创建索引)。 2. 修改表结构:如果可能,将列的数据类型更改为允许索引的类型(例如VARCHAR,并指定足够长度),但这取决于实际存储的数据类型和大小。 具体步骤(以创建索引为例): 假设我们有一个表`my_table`,其中有一个TEXT类型的列`cInvCode`,我们想要在`cInvCode`上创建索引,那么我们可以这样写: ```sql CREATE INDEX idx_cInvCode ON my_table (cInvCode(50)); -- 指定前缀长度为50个字符 ``` 注意:前缀长度的选择应该根据实际数据情况。长度太短可能达不到索引的效果,太长则可能浪费空间并降低索引效率。通常,我们可以通过分析数据的前缀区分度来确定合适的长度。 另外,引用[2]提到,在严格模式下,TEXT/BLOB列不能设置默认值。但这与索引问题无关,是另一个需要注意的点。 根据引用[4],BLOBTEXT类型有不同的大小限制,比如TinyBlob(255字节)、Blob(约65K)、MediumBlob(约16M)和LongBlob(约4G)。同样,TEXT类型也有对应的四种。所以,如果数据量不大,可以考虑使用VARCHAR(最大65535字节)来替代,这样在创建索引时就不需要指定前缀长度。 因此,另一个解决方案是: 如果`cInvCode`列存储的数据长度不会超过65535字节,并且数据是文本类型,那么可以考虑将列的数据类型改为VARCHAR,并指定一个最大长度(例如VARCHAR(255))。然后就可以正常创建索引了。 但是,如果数据是二进制数据(如图片、音频等),则应该使用BLOB类型,并且索引必须指定前缀长度(但通常不建议对二进制大对象创建索引,因为二进制数据的前缀区分度可能不高)。所以,需要确认`cInvCode`列的具体用途和数据类型。 总结解决方法: 方法1:创建索引时指定前缀长度(适合保留原有TEXT/BLOB类型的情况) 方法2:修改列数据类型为VARCHAR(如果数据是字符串且长度在VARCHAR允许范围内)或使用其他允许索引的类型(如整数等),然后再创建索引。 根据引用[5],我们也应该注意表的设计,避免不必要的大字段,尤其是当数据量很大时,大字段会占用大量存储空间,且影响性能。 因此,在实际操作前,还需要考虑: - `cInvCode`列的实际用途:它是存储什么类型的数据?是文本还是二进制? - 数据长度的分布:大部分数据长度是多少?是否需要存储很大的数据? - 是否必须在该列上建立索引?是否有其他替代方案(如使用其他列建立索引)? 操作建议: 1. 首先,分析一下`cInvCode`列的数据,如果是文本数据且长度不太长(比如小于1000字符),那么可以考虑将其改为VARCHAR类型,并设置合适的长度(如VARCHAR(1000))。 2. 如果必须保留为TEXT类型,那么在创建索引时指定一个合适的前缀长度(如50或100,具体根据数据特点选择)。 示例(修改表结构): ```sql -- 假设原列是TEXT类型,我们改为VARCHAR(1000) ALTER TABLE my_table MODIFY cInvCode VARCHAR(1000); -- 然后再创建索引 CREATE INDEX idx_cInvCode ON my_table (cInvCode); ``` 示例(创建索引时指定前缀长度): ```sql -- 不修改列类型,直接创建索引并指定前缀长度 CREATE INDEX idx_cInvCode ON my_table (cInvCode(100)); ``` 最后,请注意操作前备份数据,以防万一。 相关问题: 1. 如何确定索引前缀长度? 2. 在MySQL中,如何查看表中列的当前数据类型? 3. 除了指定前缀长度,还有哪些方法可以解决BLOB/TEXT列不能直接索引的问题? 4. 为什么MySQL不允许对BLOB/TEXT类型的列直接创建索引? </think> ### 解决 MySQLBLOB/TEXT 列 'cInvCode' 在键规范中使用但没有键长度的问题 #### 问题原因 MySQL 不允许直接对 `BLOB` 或 `TEXT` 类型的列创建索引或主键,因为它们可能包含超大体积数据(最大可达 4GB)[^4]。错误信息 `BLOB/TEXT column 'cInvCode' used in key specification without a key length` 表明您在以下操作中未指定索引前缀长度: ```sql CREATE INDEX idx_cInvCode ON your_table (cInvCode); -- 错误示例 ALTER TABLE your_table ADD PRIMARY KEY (cInvCode); -- 错误示例 ``` #### 解决方案 1. **指定索引前缀长度(推荐)** 只索引列的前 N 个字符: ```sql -- 创建索引(假设前缀长度 100) CREATE INDEX idx_cInvCode ON your_table (cInvCode(100)); -- 添加唯一约束(如适用) ALTER TABLE your_table ADD UNIQUE (cInvCode(50)); ``` 2. **修改列数据类型(如果可行)** 若 `cInvCode` 的实际值长度较小(≤ 65,535 字节),改用 `VARCHAR`: ```sql ALTER TABLE your_table MODIFY cInvCode VARCHAR(255); -- 根据实际最大长度调整 ``` 3. **调整表设计(长期优化)** - 避免在 `TEXT/BLOB` 列上建立索引,改用其他短列(如 ID) - 对大字段表进行分表设计,分离高频查询字段[^5] #### 注意事项 1. **前缀长度选择原则**: - 确保长度足够区分数据(例如 `cInvCode(20)` 比 `cInvCode(2)` 更安全) - 通过数据分布验证: ```sql SELECT COUNT(DISTINCT cInvCode) AS total_unique, COUNT(DISTINCT LEFT(cInvCode, 100)) AS prefix_unique FROM your_table; -- 若 prefix_unique/total_unique ≥ 0.95 则长度可用 ``` 2. **存储引擎限制**: - InnoDB 索引前缀最大 767 字节(若使用 UTF8MB4,最多支持 `191` 字符) ```sql -- 计算最大可用前缀长度 SELECT 767 / CHAR_LENGTH('A'); -- 单字节字符返回 767 SELECT 767 / CHAR_LENGTH('中'); -- UTF8MB4 字符返回 191 ``` 3. **性能影响**: - 前缀索引可能导致索引覆盖失效(无法完全覆盖 `TEXT` 列) - 排序操作仍需要使用完整列值(即使使用前缀索引)[^1] #### 操作示例 ```sql -- 1. 验证列数据类型 SHOW CREATE TABLE your_table; -- 2. 创建带前缀长度的索引 CREATE INDEX idx_prefix_cinv ON your_table (cInvCode(100)); -- 3. 修改列类型方案(如果数据允许) ALTER TABLE your_table MODIFY cInvCode VARCHAR(500) NOT NULL COMMENT '转成可索引类型'; ``` > **关键提示**:生产环境操作前务必备份数据,大表修改建议在低峰期进行[^5]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值