Mysql创建外键时[Err] 1005 - Can't create table 'xx' (errno: 150) 解决方案

本文解析了pymysql.err.InternalError错误,提供了四种常见解决方案,包括数据类型、表引擎、约束名及编码格式的问题排查与修复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

具体错误如下:

pymysql.err.InternalError: (1005, "Can't create table 'bigdt.#sql-3f2_f045' (errno: 150)")

看到这个错误挺让人头秃的,莫名其妙。总的来说解决方向大致分为:

1、数据类型不相同,可能一个int,一个int unsigned。

2、数据表引擎不一样,统一改成INNODB就行。

3、约束名已经存在,改一个新的名字。

语法:创建表时 指定外键约束 :

constraint   约束名称  foreign  key(外键列名)   references  关联表 (关联表的主键);

4、数据表支持的编码格式不一样。

 

参考博客:

https://blog.youkuaiyun.com/yangzaiqiu1986814/article/details/17009601

https://blog.youkuaiyun.com/kxp9545/article/details/73302267

from re import match import mysql.connector import requests from bs4 import BeautifulSoup from mysql.connector import errorcode headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'} conn = mysql.connector.connect( host="localhost", user="root", password="123456", database="test" ) cursor = conn.cursor() def create_tables(): tables = { 'students': ( "CREATE TABLE students (" "id INT AUTO_INCREMENT PRIMARY KEY," "name VARCHAR(50) NOT NULL," "sex VARCHAR(50) NOT NULL," "age INT" ")" ), 'class': ( "CREATE TABLE class (" "id INT AUTO_INCREMENT PRIMARY KEY," "class_name VARCHAR(50) NOT NULL," "class_score INT" ")" ), 'score': ( "CREATE TABLE score (" "id INT AUTO_INCREMENT PRIMARY KEY," "student_id INT NOT NULL," "class_id INT NOT NULL," "score DECIMAL(5,2) CHECK (score BETWEEN 0 AND 100)," "FOREIGN KEY (student_id) REFERENCES students(id)" " ON UPDATE CASCADE ON DELETE RESTRICT," # 注意逗号分隔 "FOREIGN KEY (class_id) REFERENCES class(id)" " ON UPDATE CASCADE ON DELETE RESTRICT" ")" ) } try: # 按依赖顺序创建表 cursor.execute(tables['students']) cursor.execute(tables['class']) cursor.execute(tables['score']) conn.commit() print("表创建成功") except mysql.connector.Error as err: if err.errno == errorcode.ER_TABLE_EXISTS_ERROR: print("表已存在") else: print(f"创建失败: {err.msg}") def insert_student(table, data): try: placeholders = ', '.join(['%s'] * len(data[0])) sql = f"INSERT INTO {table} (id, name, sex, age) VALUES ({placeholders})" cursor.executemany(sql, data) except mysql.connector.Error as err: if err.errno == errorcode.ER_TABLE_EXISTS_ERROR: print("none") else: print(f"插入失败: {err.msg}") def insert_score(table, data): try: placeholders = ', '.join(['%s'] * len(data[0])) sql = f"INSERT INTO {table} (student_id, class_id, score) VALUES ({placeholders})" cursor.executemany(sql, data) except mysql.connector.Error as err: if err.errno == errorcode.ER_TABLE_EXISTS_ERROR: print("none") else: print(f"插入失败: {err.msg}") def get_data(url): re = requests.get(url, headers=headers).json() for i in range(2,len(re)): stu = [[re[i][0], re[i][1], re[i][2], re[i][3]]] insert_student('students',stu) if re[i][4] == '语文': sco = [[re[i][0], 1, re[i][5]]] insert_score('score',sco) if re[i][4] == '英语': sco = [[re[i][0], 2, re[i][5]]] insert_score('score', sco) if re[i][4] == '数学': sco = [[re[i][0], 3, re[i][5]]] insert_score('score', sco) # 执行创建 create_tables() get_data('http://article.xishanyigu.com/index/index/test')
最新发布
07-19
<think>嗯,用户遇到了MyBatis创建出现错误1005errno 150的问题,需要解决。首先,我应该回忆一下MySQL中常见的错误代码。记得错误1005通常与约束有关,而errno 150可能涉及创建失败的具体原因。 首先,用户可能是在使用MyBatis执行建表语句遇到了问题。这候需要检查约束是否正确。比如,引用的表和字段是否存在,数据类型是否匹配,字符集和排序规则是否一致。这些都是常见的原因。 接下来,名称是否重复也可能导致这个问题。MySQL要求名称在数据库中唯一,如果已经有同名的存在,就会报错。此,存储引擎是否支持也很重要,比如MyISAM不支持,而InnoDB支持,所以用户需要确认表是否使用了InnoDB引擎。 还有,索引的问题。字段必须要有索引,如果父表的引用字段没有索引,或者子表的字段没有创建索引,也会导致错误。需要检查相关字段的索引情况。 用户可能没有详细描述具体的表结构,所以建议用户提供建表语句,这样可以更具体地排查问题。同,查看MySQL的错误日志,里面可能有更详细的错误信息,帮助定位问题。 另,MyBatis的配置是否正确?比如是否开启了自动提交事务,或者是否有其他配置导致约束无法正确应用。虽然MyBatis本身不处理,但执行SQL的方式可能会影响。例如,是否在一个事务中创建了父表和子表,导致父表还没提交,子表的约束就生效了。 最后,总结常见的解决方案,逐步引导用户检查这些可能的原因,并提供示例代码和查看日志的方法,帮助用户一步步解决问题。</think>### MyBatis错误1005errno 150解决方案 错误`1005 (errno 150)`在MySQL中通常与约束创建失败相关,常见于表结构定义或引用不满足条件。以下是分步排查与解决方案--- #### 1. **检查约束条件** 需满足以下条件: - **被引用的表和字段必须存在且类型一致** 例如,若字段是`INT(11)`,被引用字段也必须是`INT(11)`,而非`BIGINT`或`VARCHAR`。 - **字符集和排序规则需一致** 若父表字段使用`utf8mb4_general_ci`,子表字段也需相同配置[^1]。 - **字段需有索引** 子表的字段必须显式创建索引(父表字段自动生成索引)。 **示例错误代码:** ```sql -- 父表 CREATE TABLE parent ( id INT PRIMARY KEY ) ENGINE=InnoDB; -- 子表(错误示例:未显式为user_id创建索引) CREATE TABLE child ( id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES parent(id) ); ``` --- #### 2. **验证名称唯一性** 名称需在数据库内唯一,重复名称会导致错误。可通过以下语句检查: ```sql SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 'your_table'; ``` --- #### 3. **检查存储引擎兼容性** 确保**父表和子表均使用InnoDB引擎**(MyISAM不支持): ```sql SHOW CREATE TABLE parent; SHOW CREATE TABLE child; ``` --- #### 4. **验证引用完整性** - **被引用字段必须是主或唯一索引** 若父表字段未定义为主或唯一索引,将无法创建- **禁止循环依赖** 例如,表A引用表B,表B又引用表A。 --- #### 5. **MyBatis映射文件检查** 确保SQL语句语法正确,避免因MyBatis动态SQL拼接导致字段类型或名称错误: ```xml <!-- 正确的定义示例 --> <update id="createChildTable"> CREATE TABLE child ( id INT PRIMARY KEY, user_id INT, INDEX idx_user_id (user_id), FOREIGN KEY (user_id) REFERENCES parent(id) ) ENGINE=InnoDB; </update> ``` --- #### 6. **查看详细错误日志** 通过MySQL日志获取具体错误原因: ```sql SHOW ENGINE INNODB STATUS; -- 查看 "LATEST FOREIGN KEY ERROR" 部分 ``` --- #### 7. **其他常见原因** - **事务未提交**:确保父表在创建前已提交事务。 - **字段符号不匹配**:如`UNSIGNED`属性需在父子表中一致。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值