Python开发【第十一篇】:Python操作MySQL
本篇对于Python操作MySQL主要使用两种方式:
1、原生模块pymsql。
2、ORM框架SQLAchemy。
pymsql
pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同。
windows下载安装
- pip3 install pymysql
使用操作
执行SQL
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import pymysql
- # 创建连接
- conn = pymysql.connect(host='192.168.31.134',port=3306,user='root',passwd='123456',db='information_schema')
- # 创建游标
- cursor = conn.cursor()
- # 执行SQL,并返回受影响行数
- effect_row = cursor.execute("select * from tables")
- print(effect_row)
- # 取出一条数据
- print(cursor.fetchone())
- # 取出前n条数据
- print("*********************************************************")
- print(cursor.fetchmany(5))
- # 取出所有数据
- print("*********************************************************")
- print(cursor.fetchall())
- # 提交,不然无法保存新建或修改的数据
- conn.commit()
- # 关闭游标
- cursor.close()
- # 关闭连接
- conn.close()
可能报错:pymysql.err.InternalError: (1130, "Host '192.168.31.1' is not allowed to connect to this MySQL server")
可能是因为你的账号不允许从远程登录,只能在localhost登录。只需要在localhost的那台电脑登录mysql,更改对应数据库里的"user"表里的"host"项,把"localhost"改为"%"。
解决办法:
1、改表法
- [root@lnmp ~]# mysql -uroot -p123456
- mysql> use test;
- Database changed
- mysql> update user set host = '%' where user = 'root';
- mysql> select host,user from user;
- mysql> flush rivileges;
2、授权法
允许用户user使用密码password从任何主机连接到mysql服务器。
- mysql> grant all privileges on *.* to 'user'@'%' identified by 'password' with grant option;
- mysql> flush privileges;
允许用户user从ip192.168.1.122的主机连接到mysql服务器,并使用password作为密码。
- mysql> grant all privileges on *.* to 'user'@'192.168.1.122' identified by 'password' with grant option;
- mysql> flush privileges;
允许用户user从ip192.168.1.122的主机连接到mysql服务器的test_db数据库,并使用password作为密码。
- mysql> grant all privileges on test_db.* to 'user'@'192.168.1.122' identified by 'password' with grant option;
- mysql> flush privileges;
插入数据
- # 插入数据
- effect_row = cursor.executemany("inster into table_name(field_name1,field_name2) values(%s,%s)",[("value_1","value_2"),("value_3","value_4")])
SQLAlchemy ORM
ORM介绍
对象关系映射(Object Relational Mapping,简称ORM),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的——"虚拟对象数据库"。
面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。
对象关系映射(Object Relational Mapping)提供了概念性的、易于理解的模型化数据的方法。ORM方法论基于三个核心原则。简单,以最基本的形式建模数据。传达性,数据库结构被任何人都能理解的语言文档化。精确性,基于数据模型创建正确标准化的结构。典型地,建模者通过收集来自那些熟悉应用程序但不熟练数据建模者开发信息模型。建模者必须能够用非技术企业专家可以理解的术语在概念层次上与数据结构进行通讯。建模者也必须能以简单的单元分析信息,对样本数据进行处理。ORM专门被设计为改进这种联系。
ORM的优点
1、隐藏了数据访问细节,"封闭"的通用数据库交互,ORM的核心。使得通用数据库的交互变得简单易行,并且完全不用考虑SQL语句。
2、ORM使构造固化数据结构变得简单易行。
ORM的缺点
1、自动化意味着映射和关联管理,代价是牺牲性能。现在各种ORM框架都在尝试使用各种方法(如LazyLoad、Cache)来减轻性能的影响,效果比较显著。
2、面向对象的查询语言(OQL)作为一种数据库与对象之间的过渡,虽然隐藏了数据层面的业务抽象,但并不能完全的屏蔽掉数据库层的设计,并且无疑将增加学习成本。
3、对于复杂查询,ORM仍然力不从心。虽然可以实现,但是不值得。视图可以解决大部分calculated column、case、group、having、order by、exists,但是查询条件a and b and not c and (d or e)不能很好解决。
常用的ORM框架
1、Hibernate全自动需要hql语句。
2、iBatis半自动自己写sql语句,可操作性强,小巧。
3、EclipseLink一个可扩展的支持JPA的ORM框架,提供强大的缓存功能,缓存支持集群。
4、Apache OJB等等。
5、在Python中最著名的ORM框架是SQLAlchemy。
SQLAlchemy安装
SQLAlchemy的理念是,SQL数据库的量级和性能重要于对象集合,而对象集合的抽象又重要与表和行。
Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作。
- MySQL-Python
- mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
- pymysql
- mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
- MySQL-Connector
- mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
- cx_Oracle
- oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
- 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
安装sqlalchemy
- pip3 install sqlalchemy
SQLAlchemy基本使用
创建一个表。
SQL实现:
- CREATE TABLE USER(
- ID INTEGER NOT NULL AUTO_INCREMENT,
- NAME VARCHAR(32),
- PASSWORD VARCHAR(64),
- PRIMARY KET (ID)
- )
ORM实现:
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine
- from sqlalchemy.ext.declarative import declarative_base
- from sqlalchemy import Column,Integer,String
- # echo=True打印信息
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=True)
- # 生成orm基类
- Base = declarative_base()
- class User(Base):
- # 表名
- __tablename__ = 'USER'
- # 定义字段ID,并设置为主键
- ID = Column(Integer,primary_key=True)
- NAME = Column(String(32))
- PASSWORD = Column(String(64))
- # 创建表结构
- Base.metadata.create_all(engine)
除了上面的创建表之外,还有一种创建表的方式。
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine,Table,MetaData,Column,Integer,String,ForeignKey
- from sqlalchemy.orm import mapper
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=True)
- metadata = MetaData()
- user = Table('USER_TABLE',metadata,
- Column('ID',Integer,primary_key=True),
- Column('NAME',String(50)),
- Column('FULLNAME',String(50)),
- Column('PASSWORD',String(12))
- )
- class User(object):
- def __init__(self,name,fullname,password):
- self.name = name
- self.fullname = fullname
- self.password = password
- mapper(User,user)
- # 创建表结构
- metadata.create_all(engine)
第一种方式创建的表是基于第二种方式的再封装。
使用ORM创建一条数据。
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine,Column,Integer,String
- from sqlalchemy.orm import sessionmaker
- from sqlalchemy.ext.declarative import declarative_base
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=True)
- Base = declarative_base()
- class User(Base):
- __tablename__ = 'USER'
- ID = Column(Integer,primary_key=True)
- NAME = Column(String(32))
- PASSWORD = Column(String(64))
- Base.metadata.create_all(engine)
- # 创建与数据库的会话session class,注意这里返回给session的是一个class,不是实例
- Session_class = sessionmaker(bind=engine)
- # 生成session实例
- Session = Session_class()
- # 生成要创建的数据对象
- user_obj = User(NAME="Golden",PASSWORD="123456")
- # 此时还没有创建对象
- print(user_obj.NAME,user_obj.ID)
- # 把需要创建的数据对象添加到session
- Session.add(user_obj)
- # 此时还没有创建对象
- print(user_obj.NAME,user_obj.ID)
- # 创建数据,统一提交
- Session.commit()
查询、修改
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine,Column,Integer,String
- from sqlalchemy.ext.declarative import declarative_base
- from sqlalchemy.orm import sessionmaker
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=False)
- Base = declarative_base()
- class User(Base):
- __tablename__ = 'USER'
- ID = Column(Integer,primary_key=True)
- NAME = Column(String(32))
- PASSWORD = Column(String(64))
- def __repr__(self):
- return "<NAME : %s | PASSWORD : %s>" %(self.NAME,self.PASSWORD)
- Session_class = sessionmaker(bind=engine)
- Session = Session_class()
- # first 查出NAME='Golden'的第一个
- my_user = Session.query(User).filter_by(NAME='Golden').first()
- print(my_user.NAME,my_user.PASSWORD)
- # NAME='Golden'
- data = Session.query(User).filter_by(NAME='Golden').all()
- print(data[0].PASSWORD)
- #all 查出所有
- data_2 = Session.query(User).filter_by().all()
- print(data_2)
- data_3 = Session.query(User).filter(User.ID == 1).all()
- print(data_3)
- data_4 = Session.query(User).filter_by(ID=1).all()
- print(data_4)
- # 多条件查询
- data_5 = Session.query(User).filter(User.ID > 1).filter(User.ID < 4).all()
- print(data_5)
- data_6 = Session.query(User).filter().first()
- print(data_6)
- # 修改
- data_6.NAME = 'zhangsan'
- data_6.PASSWORD = '110'
- # 提交
- Session.commit()
回滚
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine,Column,Integer,String
- from sqlalchemy.ext.declarative import declarative_base
- from sqlalchemy.orm import sessionmaker
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=False)
- Base = declarative_base()
- class User(Base):
- __tablename__ = 'USER'
- ID = Column(Integer,primary_key=True)
- NAME = Column(String(32))
- PASSWORD = Column(String(64))
- def __repr__(self):
- return "<ID : %s | NAME : %s | PASSWORD : %s>" %(self.ID,self.NAME,self.PASSWORD)
- Session_class = sessionmaker(bind=engine)
- Session = Session_class()
- my_user = Session.query(User).filter_by(ID=1).first()
- my_user.NAME = 'Mark'
- fake_user = User(NAME='Merry',PASSWORD='999999')
- Session.add(fake_user)
- # 查看刚刚添加和修改的数据
- print(Session.query(User).filter(User.NAME.in_(['Merry','Mark'])).all())
- # rollback
- Session.rollback()
- # 再次查询
- print(Session.query(User).filter(User.NAME.in_(['Merry','Mark'])).all())
统计和分组
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine,Column,Integer,String,func
- from sqlalchemy.ext.declarative import declarative_base
- from sqlalchemy.orm import sessionmaker
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=False)
- Base = declarative_base()
- class User(Base):
- __tablename__ = 'USER'
- ID = Column(Integer,primary_key=True)
- NAME = Column(String(32))
- PASSWORD = Column(String(64))
- def __repr__(self):
- return "<ID : %s | NAME : %s | PASSWORD : %s>" %(self.ID,self.NAME,self.PASSWORD)
- Session_class = sessionmaker(bind=engine)
- Session = Session_class()
- # 统计ha开头的NAME个数
- print(Session.query(User).filter(User.NAME.like("ha%")).count())
- # 分组
- print(Session.query(User.NAME,func.count(User.NAME)).group_by(User.NAME).all())
连表
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine,Column,Integer,String,DATE
- from sqlalchemy.orm import sessionmaker
- from sqlalchemy.ext.declarative import declarative_base
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=True)
- Base = declarative_base()
- class User(Base):
- __tablename__ = 'USER'
- ID = Column(Integer,primary_key=True)
- NAME = Column(String(32))
- PASSWORD = Column(String(64))
- def __repr__(self):
- return "<ID :%s | NAME : %s | PASSWORD : %s>" %(self.ID,self.NAME,self.PASSWORD)
- class Student(Base):
- __tablename__ = 'STUDENT'
- ID = Column(Integer,primary_key=True)
- NAME = Column(String(32),nullable=False)
- REGISTER_DATE = Column(DATE,nullable=False)
- GENDER = Column(String(32),nullable=False)
- def __repr__(self):
- return "<NAME : %s | PASSWORD : %s>" %(self.NAME,self.REGISTER_DATE)
- Base.metadata.create_all(engine)
- Session_class = sessionmaker(bind=engine)
- Session = Session_class()
- # 外联
- print(Session.query(User,Student).filter(User.ID == Student.ID).all())
- # 两个表必须有外键关联才能使用 Can't find any foreign key relationships between 'A' and 'B'
- print(Session.query(User).join(Student).all())
- print(Session.query(User).join(Student,isouter=True).all())
- Session.commit()
实现两个表的外键关联
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import sqlalchemy
- from sqlalchemy import create_engine,Column,Integer,String,DATE,ForeignKey
- from sqlalchemy.orm import sessionmaker,relationship
- from sqlalchemy.ext.declarative import declarative_base
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=False)
- Base = declarative_base()
- class Student(Base):
- __tablename__ = 'student'
- id = Column(Integer,primary_key=True)
- name = Column(String(32),nullable=False)
- register_date = Column(DATE,nullable=False)
- def __repr__(self):
- return "<name : %s | register_date : %s>"%(self.name,self.register_date)
- class StudyRecord(Base):
- __tablename__ = "study_record"
- id = Column(Integer,primary_key=True)
- day = Column(Integer,nullable=False)
- status = Column(String(32),nullable=False)
- # 创建外键
- stu_id = Column(Integer,ForeignKey("student.id"))
- #
- student = relationship("Student",backref="my_study_record")
- def __repr__(self):
- return "<%s day :%s | status : %s>"%(self.student.name,self.day,self.status)
- # 创建表结构
- Base.metadata.create_all(engine)
- # 创建与数据库的会话session
- Session_class = sessionmaker(bind=engine)
- # 生成session实例
- session = Session_class()
- """添加数据
- s1 = Student(name="Golden",register_date="2017-12-24")
- s2 = Student(name="Jack",register_date="2017-11-13")
- s3 = Student(name="Rain",register_date="2017-10-11")
- s4 = Student(name="Eric",register_date="2017-07-07")
- study_obj1 = StudyRecord(day=1,status="Yes",stu_id=1)
- study_obj2 = StudyRecord(day=2,status="No",stu_id=1)
- study_obj3 = StudyRecord(day=3,status="Yes",stu_id=1)
- study_obj4 = StudyRecord(day=1,status="Yes",stu_id=2)
- # 一次性全部创建
- session.add_all([s1,s2,s3,s4,study_obj1,study_obj2,study_obj3,study_obj4])
- """
- stu_obj = session.query(Student).filter(Student.name == "Golden").first()
- print(stu_obj)
- print(stu_obj.my_study_record)
- # 提交
- session.commit()
多外键关联
创建包含多外键的表结构。
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from sqlalchemy.orm import relationship
- from sqlalchemy import create_engine,Column,Integer,String,DATE,ForeignKey
- from sqlalchemy.ext.declarative import declarative_base
- Base = declarative_base()
- class Customer(Base):
- __tablename__ = 'customer'
- id = Column(Integer,primary_key=True)
- name = Column(String(64))
- billing_address_id = Column(Integer,ForeignKey("address.id"))
- shipping_address_id = Column(Integer,ForeignKey("address.id"))
- billing_address = relationship("Address",foreign_keys=[billing_address_id])
- shipping_address = relationship("Address",foreign_keys=[shipping_address_id])
- class Address(Base):
- __tablename__ = 'address'
- id = Column(Integer,primary_key=True)
- street = Column(String(64))
- city = Column(String(64))
- state = Column(String(64))
- def __repr__(self):
- return self.street
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=False)
- # 创建表结构
- # Base.metadata.create_all(engine)
插入数据和查询。
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import os,sys
- path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- sys.path.append(path)
- from day11 import orm_many_fk
- from sqlalchemy.orm import sessionmaker
- Session_class = sessionmaker(bind=orm_many_fk.engine)
- session = Session_class()
- # 创建数据
- # addr1 = orm_many_fk.Address(street="zhongshanroad",city="qiaokou",state='hankou')
- # addr2 = orm_many_fk.Address(street="dongyiroad",city="hongshan",state="wuchang")
- # addr3 = orm_many_fk.Address(street="guangshanroad",city="gaoxin",state="guanggu")
- #
- # session.add_all([addr1,addr2,addr3])
- # c1 = orm_many_fk.Customer(name="Golden",billing_address=addr1,shipping_address=addr3)
- # c2 = orm_many_fk.Customer(name="Jack",billing_address=addr2,shipping_address=addr2)
- #
- # session.add_all([c1,c2])
- # 查询数据
- obj = session.query(orm_many_fk.Customer).filter(orm_many_fk.Customer.name=="Golden").first()
- print(obj.name,obj.billing_address,obj.shipping_address)
- session.commit()
多对多关联
创建多对多关联表
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from sqlalchemy import Table,Column,Integer,String,DATE,ForeignKey,create_engine
- from sqlalchemy.orm import relationship,sessionmaker
- from sqlalchemy.ext.declarative import declarative_base
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db",
- encoding='utf-8',echo=False)
- Base = declarative_base()
- book_m2m_author = Table('book_m2m_author',Base.metadata,
- Column('book_id',Integer,ForeignKey('books.id')),
- Column('author_id',Integer,ForeignKey('authors.id')))
- class Book(Base):
- __tablename__ = 'books'
- id = Column(Integer,primary_key=True)
- name = Column(String(64))
- pub_date = Column(DATE)
- authors = relationship('Author',secondary=book_m2m_author,backref='books')
- def __repr__(self):
- return self.name
- class Author(Base):
- __tablename__ = 'authors'
- id = Column(Integer,primary_key=True)
- name = Column(String(32))
- def __repr__(self):
- return self.name
- Base.metadata.create_all(engine)
- Session_class = sessionmaker(bind=engine)
- session = Session_class()
插入数据和查询
- __author__ = 'Golden'
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import os,sys
- path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- sys.path.append(path)
- from day11 import orm_m2m
- from sqlalchemy.orm import sessionmaker
- Session_class = sessionmaker(bind=orm_m2m.engine)
- session = Session_class()
- # 创建数据
- # b1 = orm_m2m.Book(name="Python")
- # b2 = orm_m2m.Book(name="JAVA")
- # b3 = orm_m2m.Book(name="C++")
- # b4 = orm_m2m.Book(name="c#")
- #
- # a1 = orm_m2m.Author(name="Golden")
- # a2 = orm_m2m.Author(name="Jack")
- # a3 = orm_m2m.Author(name="Rain")
- #
- # b1.authors = [a1,a2]
- # b2.authors = [a1,a2,a3]
- #
- # session.add_all([b1,b2,b3,b4,a1,a2,a3])
- # session.commit()
- print("通过书表查询关联的作者".center(50,"*"))
- book_obj = session.query(orm_m2m.Book).filter_by(name="JAVA").first()
- print(book_obj.name,book_obj.authors)
- print("通过作者表查询关联的书".center(50,"*"))
- author_obj = session.query(orm_m2m.Author).filter_by(name="Golden").first()
- print(author_obj.name,author_obj.books)
- # 多对多删除,删除数据时不用管book_m2m_author,sqlalchemy会自动删除对应的数据
- # 通过书删除作者
- book_obj.authors.remove(author_obj)
- # 直接删除作者
- author_obj2 = session.query(orm_m2m.Author).filter_by(name="Jack").first()
- session.delete(author_obj2)
- session.commit()
支持中文
sqlalchemy设置编码字符集一定要在数据库访问的URL上增加charset=utf8,否则数据库的连接就不是utf8的编码格式。
- # 支持中文
- engine = create_engine("mysql+pymysql://root:123456@192.168.31.134/test_db?charset=utf8",echo=True)
posted on 2018-01-01 10:18 yinshoucheng 阅读(491) 评论(0) 编辑 收藏 举报