本篇對於Python操做MySQL主要使用兩種方式: html
一、原生模塊pymsql。 python
二、ORM框架SQLAchemy。 mysql
pymsql
pymsql是Python中操做MySQL的模塊,其使用方法和MySQLdb幾乎相同。 sql
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"改成"%"。 c#
解決辦法: windows
一、改表法 緩存
-
[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;
二、受權法 服務器
容許用戶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的優勢
一、隱藏了數據訪問細節,"封閉"的通用數據庫交互,ORM的核心。使得通用數據庫的交互變得簡單易行,而且徹底不用考慮SQL語句。
二、ORM使構造固化數據結構變得簡單易行。
ORM的缺點
一、自動化意味着映射和關聯管理,代價是犧牲性能。如今各類ORM框架都在嘗試使用各類方法(如LazyLoad、Cache)來減輕性能的影響,效果比較顯著。
二、面向對象的查詢語言(OQL)做爲一種數據庫與對象之間的過渡,雖然隱藏了數據層面的業務抽象,但並不能徹底的屏蔽掉數據庫層的設計,而且無疑將增長學習成本。
三、對於複雜查詢,ORM仍然力不從心。雖然能夠實現,可是不值得。視圖能夠解決大部分calculated column、case、group、having、order by、exists,可是查詢條件a and b and not c and (d or e)不能很好解決。
經常使用的ORM框架
一、Hibernate全自動須要hql語句。
二、iBatis半自動本身寫sql語句,可操做性強,小巧。
三、EclipseLink一個可擴展的支持JPA的ORM框架,提供強大的緩存功能,緩存支持集羣。
四、Apache OJB等等。
五、在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)