使用sqlalchemy的ORM创建外键关联时报错
2018-01-12 19:56
597 查看
在学习使用sqlalchemy模块的时候踩了一个坑,分享一下。
表里就3个字段:自增id(无符号的数字,自增id不会是负数,当然用无符号,感觉自己好专业),name 和 age(话说这个也应该是无符号)。
现在已有一张学生信息表,再创建一张学生成绩表。3个字段:考试名称、学生id、成绩。考试名和学生id作为复合主键,学生id关联信息表中的id,做外键关联:
让后,报错了。开启echo,首先是SQL语句能正常生成了:
之后是长长的报错内容,就看最后一行:
埋下隐患
我先用下面的语句创建了一张学生信息表:> CREATE TABLE student ( -> id INT UNSIGNED AUTO_INCREMENT, -> name VARCHAR(20) NOT NULL, -> age TINYINT, -> PRIMARY KEY (id) -> );
表里就3个字段:自增id(无符号的数字,自增id不会是负数,当然用无符号,感觉自己好专业),name 和 age(话说这个也应该是无符号)。
出现报错
在学习了mysql之后,学习了一下PyMySql 模块。最后是这个ORM,SQLAchemy。用这个表测试了很多命令和知识点,然后进行到使用SQLAlchemy建立外键关联的时候卡住了。之前也有SQL语句建过外键关联,也很顺利。现在已有一张学生信息表,再创建一张学生成绩表。3个字段:考试名称、学生id、成绩。考试名和学生id作为复合主键,学生id关联信息表中的id,做外键关联:
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String from sqlalchemy import ForeignKey # 外键关联需要这个 engine = create_engine("mysql+pymysql://admin:admin123@192.168.246.12/week12", encoding='utf-8', echo=True) Base = declarative_base() # 生成orm基类 class Student(Base): __tablename__ = 'student' # 表名,这张表不创建,可以写的简单点 id = Column(primary_key=True) # 只要声明你需要的字段名,主键必须声明 name = Column() # 字段类型可以不要,我们不是创建表 age = Column() class Exam(Base): __tablename__ = 'exam' name = Column(String(32), primary_key=True) student_id = Column(Integer(), ForeignKey("student.id"), primary_key=True) # 声明外键关联 score = Column(Integer, nullable=False) # 规定不能为空 Base.metadata.create_all(engine) # 创建表
让后,报错了。开启echo,首先是SQL语句能正常生成了:
CREATE TABLE exam2 ( name VARCHAR(32) NOT NULL, student_id INTEGER NOT NULL, score INTEGER NOT NULL, PRIMARY KEY (name, student_id), FOREIGN KEY(student_id) REFERENCES student (id) )
之后是长长的报错内容,就看最后一行:
sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1005, "Can't create table 'week12.exam2' (errno: 150)") [SQL: '\nCREATE TABLE exam2 (\n\tname VARCHAR(32) NOT NULL, \n\tstudent_id INTEGER NOT NULL, \n\tscore INTEGER NOT NULL, \n\tPRIMARY KEY (name, student_id), \n\tFOREIGN KEY(student_id) REFERENCES student (id)\n)\n\n'] (Background on this error at: http://sqlalche.me/e/2j85)[/code]初步排查
首先想到的是代码写错了,仔细检查。全是抄老师博客上的代码,还仔细看了视频,仔细核对。发现没写错什么。
账号权限肯定不会有问题,因为之前已经用这个账号通过python试了很多事情了,包括创建表。
这里使用了复合主键,和例子稍微有点区别,于是改成了简单的单一主键,也不行。
凭自己的能力就只能做这点了,然后上网搜。先把错误信息开头的内容,就是这些:“sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1005, "Can't create table“ 去网上搜索了一番。并没有太明确的发现。
最后智能的搜索引擎帮我提炼出了一组关键字,其中有一个是“mysql error 1005”。之前一直以为是python的报错,现在想想可能是mysql的报错,于是用这个搜索了一下。跳进新坑
这次的关键字提炼比较准确,找到的内容看上去都比较有用。
首先找到的是这个原因:“外键重复,删除该表外键“。一想,之前用SQL语句练习外键的时候已经关联了一个表了,这次要拿另外一个表关联这个键,是不是就关联不上了。我就平时一个只用过几个SELECT命令的新手,没理解那么深啊。于是一头跳进这个坑又转悠了一番,最后还算好被我跳出来了。终于醒悟
继续看看还有什么原因:“外键字段与要做外键校验的字段类型不匹配 ”。处于对自己的不自信,又去仔细看了下自己的代码,看看类型有没有写,有没声明。原表的类型因为不用创建,都被我缺省了,于是试着写全,有没用。
然后去SQL里用DESC命令看看字段类型,SQL里是这样的:
一看自己的代码里Integer()里面没声明长度,于是加上。不过pycharm显示有错误。不管,试一下,当然还是不行。
虽然这个点是错误的,但是成功的让我注意到这个我前一天创建的表里的这个unsigned标志。于是试着在代码里声明为这个字段声明是无符号的。博客和视频里都没有,自己尝试性的加在括号里,加在外层的Column括号里都不行后。最后还是只能上网搜。
这次目标很明确,就是 "sqlalchemy 无符号数字"。目标很明确,不过没人专门讲这个问题。打开网页使用Ctrl+F查找终于找到了用法:from sqlalchemy.dialects.mysql import INTEGER id = Column(INTEGER(unsigned=True), primary_key=True)跳出火坑
找对了问题,最后自然就迎刃而解了。要创建表的代码如下:from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String from sqlalchemy import ForeignKey # 外键关联需要这个 from sqlalchemy.dialects.mysql import INTEGER # 要使用无符号的整数 engine = create_engine("mysql+pymysql://admin:admin123@192.168.246.12/week12", encoding='utf-8', echo=True) Base = declarative_base() # 生成orm基类 class Student(Base): __tablename__ = 'student' # 表名,这张表不创建,可以写的简单点 id = Column(primary_key=True) # 只要声明你需要的字段名,主键必须声明 name = Column() # 字段类型可以不要,我们不是创建表 age = Column() class Exam(Base): __tablename__ = 'exam' name = Column(String(32), primary_key=True) student_id = Column(INTEGER(unsigned=True), ForeignKey("student.id"), primary_key=True) # 声明外键关联 score = Column(Integer, nullable=False) # 规定不能为空 Base.metadata.create_all(engine) # 创建表
难怪讲课演示的好好的,我抄来自己试就不对。我一般嫌用的例子不好,自己会改一改(演示的例子中用的都是标准的int类型)。然后就会出这种幺蛾子。不过还好,自己能爬出来。
相关文章推荐
- 使用navicat创建MySQL外键关联
- 使用sqlalchemy实现外键关联的例子(程序,本例子来源于sqlalchemy官网)
- 学习 python ORM 类库 SQLAlchemy 使用
- Hibernate多对多关联联合外键创建及其外键表创建
- 使用 库创建重复键关联容器
- Oracle 外键创建及使用
- Flask系列教程(二)--------------使用SQLAlchemy创建数据模型
- MySQL创建外键关联错误 - errno:150
- mysql创建外键约束时报ERROR 1005 (HY000)
- beego中orm关联查询使用解析
- 解析MySQL创建外键关联错误 - errno:150
- 使用 MAP CLASS 库创建关联容器
- echarts的应用(利用后台传回json创建统计图,以及和ext的关联使用等)
- Hibernate Annotation @mappedBy含义在使用onetoone 时候【外键双向关联】(十三)
- Python下使用sqlalchemy关联MySQL数据库,建立主外键关联关系,实现相互约束和级联删除
- MYSQL外键(Foreign Key)的创建及使用
- python使用sqlalchemy中间件对MYSQL数据库进行创建、查询、删除操作
- SQLAlchemy外键的使用一.外键的定义
- Xendesktop 7.0 使用scvmm 2012 R2 mcs 创建 windows 8/8.1 windows 2012时报错
- 一步步学习SPD2010--第九章节--使用可重用工作流和工作流表单(6)--创建初始和关联表单