python----python使用mysql

Python操做MySQL主要使用兩種方式:python

  原生模塊 pymsqlmysql

  ORM框架 SQLAchemysql

pymql

 pymsql是Python中操做MySQL的模塊,在windows中的安裝:數據庫

pip install pymysql

 

入門:咱們鏈接虛擬機中的centos中的mysql,而後查詢test數據庫中student表的數據編程

import pymysql #建立鏈接
conn = pymysql.connect(host='192.168.123.207',port=3306,user='root',passwd='root',db="test"); #建立遊標
cursor = conn.cursor() #執行sql,並返回受影響的行數
effect_row = cursor.execute("select * from student") print(effect_row)

運行結果:windows

須要給權限centos

mysql> grant all on *.* to 'root'@'%' identified by 'root'; Query OK, 0 rows affected, 1 warning (0.01 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec)

 這個時候咱們在運行上面的程序咱們就能夠看到,運行成功session

 

這是說明查詢到了5條數據,那若是咱們須要查看這五條具體的數據是什麼,咱們要用:數據結構

print(cursor.fetchone())

 cursor.fetchone()是一條一條的把數據取出來app

這裏咱們用了兩條cursor.fetchone()

若是咱們想要只取出前3條數據:

print('>>>>>',cursor.fetchmany(3))

 

一次性取出全部數據:

print('------',cursor.fetchall())

若是咱們要插入多條數據:

import pymysql #建立鏈接
conn = pymysql.connect(host='192.168.123.207',port=3306,user='root',passwd='root',db="test"); #建立遊標
cursor = conn.cursor() data = [ ("N1",23,"2015-01-01","M"), ("N2",24,"2015-01-02","F"), ("N3",25,"2015-01-03","M"), ] #執行sql,並返回受影響的行數
effect_row = cursor.executemany("insert into student (name,age,register_date,gender)values(%s,%s,%s,%s)",data) conn.commit()

 

注:executemany默認會啓動一個事務,若是沒有conn.commit(),數據將不會被插入成功

 

sqlalchemy ORM

1.ORM介紹

orm英文全稱object relational mapping,就是對象映射關係程序,簡單來講相似python這種面向對象的程序來講一切皆對象,咱們實例化一個對象,經過點的形式來調用裏面的函數。orm至關於把數據庫給實例化了,數據庫都是關係型的,經過orm將編程語言的對象模型和數據庫的關係模型創建映射關係,這樣咱們在使用編程語言對數據庫進行操做的時候能夠直接使用編程語言的對象模型進行操做就能夠了,而不用直接使用sql語言。

優勢:

1.隱藏了數據訪問細節,「封閉」的通用數據庫交互,ORM的核心。他使得咱們的通用數據庫交互變得簡單易行,而且徹底不用考慮該死的SQL語句

2.ORM使咱們構造固化數據結構變得簡單易行

2.sqlalchemy安裝

安裝:

pip install sqlalchemy

3.sqlalchemy基本使用 

 首先咱們看一下咱們沒有用orm以前咱們建立一個數據表是這個樣的:

create table student( id int auto_increment, name char(32) not null, age int not null, register_date date not null, primary key(id) );

 使用了orm,實現上面的表的建立,代碼以下:

import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String engine = create_engine("mysql+pymysql://root:root@192.168.123.207/test",encoding='utf-8',echo=True) Base = declarative_base()#生成orm基類

class User(Base): __tablename__ = 'user'#表名
    id = Column(Integer,primary_key=True) name = Column(String(32)) password = Column(String(64)) Base.metadata.create_all(engine)#建立表結構

 

 用orm建立一條數據:

import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String from sqlalchemy.orm import sessionmaker engine = create_engine("mysql+pymysql://root:root@192.168.123.207/test",encoding='utf-8',echo=True) Base = declarative_base()#生成orm基類

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 = sessionmaker(bind=engine)#建立與數據庫的會話session class ,注意這裏返回給session的是一個類,不是實例
Session = Session_class()#生成session實例
 user_obj = User(name = "xiaoming" , password = "123456")#生成你要建立的數據對象
user_obj2 = User(name = "jack" , password = "123564")#生成你要建立的數據對象
print(user_obj.name,user_obj.id)#此時尚未建立對象,打印一下會發現id仍是None
 Session.add(user_obj) Session.add(user_obj2) print(user_obj.name,user_obj.id)#此時也依然尚未建立
 Session.commit()#如今才統一提交,建立數據

插入數據是使用sessionmaker,經過綁定上面建立的鏈接建立出一個類,生成session實例(至關於以前的cursor),用面向對象的方式建立兩條記錄,而後添加,最後commit就能夠了

 

下面咱們來看看數據庫的增刪改查:

查詢:

import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String
from sqlalchemy.orm import sessionmaker

engine = create_engine("mysql+pymysql://root:root@192.168.123.207/test",encoding='utf-8')
Base = declarative_base()#生成orm基類

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 = sessionmaker(bind=engine)#建立與數據庫的會話session class ,注意這裏返回給session的是一個類,不是實例
Session = Session_class()#生成session實例
data=Session.query(User).filter_by(name="xiaoming").all() #print(data[0].name,data[0].password)
print(data)

 若是隻是Session.query(User).filter_by(name="xiaoming"),只會看到一條sql語句:

filter_by()查出來的是一個列表,是一組數據

加上.all()

這個是一個對象,這也看不出來是那個,因此咱們要手動去調出數據

咱們用print(data[0].name,data[0].password):

這樣就查出了數據

如今是查一條數據,若是filter_by()裏面什麼都不寫:

data=Session.query(User).filter_by().all()

 

咱們就查出了好幾條數據,咱們要循環才能看出來具體的數據。咱們想要直接看到誰是誰,咱們怎麼辦呢?

import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String from sqlalchemy.orm import sessionmaker engine = create_engine("mysql+pymysql://root:root@192.168.123.207/test",encoding='utf-8') Base = declarative_base()#生成orm基類

class User(Base): __tablename__ = 'user'#表名
    id = Column(Integer,primary_key=True) name = Column(String(32)) password = Column(String(64)) def __repr__(self): return "<%s name:%s>" % (self.id,self.name) Base.metadata.create_all(engine)#建立表結構
 Session_class = sessionmaker(bind=engine)#建立與數據庫的會話session class ,注意這裏返回給session的是一個類,不是實例
Session = Session_class()#生成session實例
 data=Session.query(User).filter_by().all() print(data)

 咱們添加了__repr__()函數,這樣看看運行結果:

這樣就顯現出咱們查詢的結果了。就至關於,若是你要查看什麼數據,以什麼格式的方式顯示,就能夠在__repr__這個函數中設置

在這裏,咱們用filter_by().all()查詢出全部的數據,那咱們用filter_by().first(),就能夠查詢出數據庫中的第一條數據 

上面咱們用filter_by(name="xiaoming")查詢出了姓名爲xiaoming的數據,那咱們想要查詢用戶id>1的數據應該怎麼查詢呢?

data=Session.query(User).filter(User.id>1).all()
多個條件查詢:再加幾個filter
data=Session.query(User).filter(User.id>1).filter(User.id<3).all()

 

 修改:

data=Session.query(User).filter(User.id>1).first() print(data) data.name = "Jack Chen" data.password = "555555" Session.commit()

查詢到你要修改的這個數據,而後想修改面向對象裏的數據同樣,對數據進行修改,最後commit()就能夠了

 

刪除:

data = Session.query(User).filter_by(name = 'Rain').first() Session.delete(data) Session.commit()

 

一樣的,先查詢到要刪除的數據,而後對數據進行刪除,最後提交commit

 

回滾:

fake_user = User(name = 'Rain',password = "123456") Session.add(fake_user) print(Session.query(User).filter(User.name.in_(['jack','rain'])).all())#這時候看看session裏有了剛剛添加的數據
 Session.rollback()#此時你rollback一下

print(Session.query(User).filter(User.name.in_(['jack','rain'])).all())#再查就發現剛剛添加的數據就沒有了

運行結果看看:

這個時候能夠看到一開始咱們是可以看到剛剛插入的數據,可是回滾以後咱們就看不到了,咱們到數據庫中看看:

 

咱們插入一條數據看看

能夠看出咱們插入的數據的id是4,這樣看來確實是先插入進去,而後回滾以後刪除的

 

分組 統計:

統計:

Session.query(User).filter(User.name.in_(['xiaoming','rain'])).count()

 分組:

from sqlalchemy import func print(Session.query(func.count(User.name),User.name).group_by(User.name).all())

 

 join多表查詢:

Session.query(User,Student).filter(User.id == Student.id).all() Session.query(User).join(Student).all()#這種寫法必需要求兩個表有外鍵關聯

外鍵關聯

咱們先建立兩個表student,study_record:

import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String,DATE,ForeignKey from sqlalchemy.orm import sessionmaker engine = create_engine("mysql+pymysql://root:root@192.168.123.207/xumingdb",encoding='utf-8') Base = declarative_base()#生成orm基類

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 "<%s name:%s>" % (self.id,self.name) 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")) def __repr__(self): return "<%s day:%s>" % (self.id,self.day) Base.metadata.create_all(engine)#建立表結構

 

外鍵表的建立,要用到ForeignKey("student.id")裏面就直接是表名.字段名 

而後向兩個表中插入數據:

Base.metadata.create_all(engine)#建立表結構
Session_class = sessionmaker(bind=engine) session = Session_class() s1 = Student(name = "xiaoming",register_date="2015-06-07") s2 = Student(name = "huahua",register_date="2015-06-08") s3 = Student(name = "caicai",register_date="2015-06-09") s4 = Student(name = "zhazha",register_date="2015-06-04") 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]) session.add_all([study_obj1,study_obj2,study_obj3,study_obj4]) session.commit()

 

 批量插入用add_all,裏面用一個列表放入要插入的數據,注意的是,由於創建了外鍵,因此在添加數據的時候,study_record的數據必定要在student表數據插入以後纔可以被插入,若是一塊兒插入就會報錯

 如今咱們要查詢xiaoming一共上了幾節課,那應該怎麼作呢:

import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column,Integer,String,DATE,ForeignKey from sqlalchemy.orm import sessionmaker,relationship engine = create_engine("mysql+pymysql://root:root@192.168.123.207/xumingdb",encoding='utf-8') Base = declarative_base()#生成orm基類

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 "<%s name:%s>" % (self.id,self.name) 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_class = sessionmaker(bind=engine) session = Session_class()
stu_obj = session.query(Student).filter(Student.name=='xiaoming').first() 
print(stu_obj.my_study_record)
session.commit()

 注意上面代碼標紅的這個語句,咱們引入了relationship,而後這個容許你在study_record表裏經過backref字段反向查出全部它在student表裏的關聯項,實現了一個雙向查找,即關聯student表,在studyrecord中經過student字段就能夠查 student表中的全部字段,反過來,咱們能夠在student表中經過 my_study_record字段反查studyrecord裏面的數據,而後表明着咱們在下面查到的xiaoming,能夠.my_study_record就能夠查詢出在studyrecord表中還有xiaoming的id的數據項

 多外鍵關聯

 首先咱們建立兩個表customer和address兩個表,其中customer表中有address的兩個外鍵:

import sqlalchemy from sqlalchemy import Integer, ForeignKey, String, Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:root@192.168.123.207/xumingdb",encoding='utf-8') 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") shipping_address = relationship("Address") 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
Base.metadata.create_all(engine) # 建立表結構

 而後咱們向兩個表中插入數據:

from day12 import sqlalchemy_multi_fk from sqlalchemy.orm  import sessionmaker Session_class = sessionmaker(bind=sqlalchemy_multi_fk.engine) session = Session_class() addr1 = sqlalchemy_multi_fk.Address(street="XiZangBeiLu",city="ShangHai",state="ShangHai") addr2 = sqlalchemy_multi_fk.Address(street="YuHu",city="XiangTan",state="HuNan") addr3 = sqlalchemy_multi_fk.Address(street="ZhongXinZhen",city="SuQian",state="JiangSu") session.add_all([addr1,addr2,addr3]) c1 = sqlalchemy_multi_fk.Customer(name="xiaoming",billing_address=addr1,shipping_address=addr2) c2 = sqlalchemy_multi_fk.Customer(name="jack",billing_address=addr3,shipping_address=addr3) session.add_all([c1,c2]) session.commit()

 

 這樣插入會出現一個錯誤:

sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship Customer.billing_address - there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.

說白了就是咱們如今在作關聯查詢的時候,有兩個字段同時關聯到了Address表中 ,在作反向查詢的時候它分不清楚誰是誰,經過address反向查的時候分不清哪一個字段表明billing_address,哪一個字段是表明了shipping_address.那咱們怎麼解決呢?

billing_address = relationship("Address",foreign_keys=[billing_address_id]) shipping_address = relationship("Address",foreign_keys=[shipping_address_id])

在建立反向查詢的語句中添加foreign_keys參數就能夠了

 

添加數據成功!!

這個時候咱們要查詢customer的地址:

obj = session.query(sqlalchemy_multi_fk.Customer).filter(sqlalchemy_multi_fk.Customer.name=="xiaoming").first() print(obj.name,obj.billing_address,obj.shipping_address)

 

 多對多關係

 如今讓咱們設計一個能描述「圖書」與「做者」的關係的表結構,需求是:

1.一本書能夠有好幾個做者一塊兒出版

2.一個做者能夠寫好幾本書

首先咱們看一下通常的思路 :

兩個表,而後咱們在遇到一本書有多個做者共同參與出版,就把做者id寫在一塊兒,可是這樣不利於查詢

那咱們能夠再添加一張表:

這就實現了雙向的一對多,一個做者能夠包含多本書,一本書能夠包含多個做者。這就造成了多對多。

來看代碼的實現:

首先仍是先創建數據表:

from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:root@192.168.123.207/xumingdb",encoding='utf-8') Base = declarative_base() 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) # 建立表結構

這裏咱們使用了另一種創建表的方式,創建了第三張表book_m2m_auther,這張表創建起來後基本上不須要咱們去人爲的添加數據,對用戶來說是不用關心這裏面有什麼數據,是由orm自動幫你維護的。也就不須要給它創建映射關係了。

可是在mysql端其實已經關聯上了,由於外鍵已經創建好了,在orm查詢的時候,還要作一個orm級別的 內存對象的映射:relationship,告訴book表和author表在查詢數據的時候去哪張表裏查詢。

因此看上面的紅色的代碼,經過secondary這個字段去查第三張表。

這個時候就創建好了多對多的關係。咱們就能夠插入數據看效果:(先把表創建起來再說)

from day12 import sqlalchemy_multitomulti from sqlalchemy.orm  import sessionmaker Session_class=sessionmaker(bind=sqlalchemy_multitomulti.engine) session = Session_class() b1 = sqlalchemy_multitomulti.Book(name="book1",pub_date="2014-05-16") b2 = sqlalchemy_multitomulti.Book(name="book2",pub_date="2012-03-16") b3 = sqlalchemy_multitomulti.Book(name="book3",pub_date="2016-06-16") a1 = sqlalchemy_multitomulti.Author(name="xiaoming") a2 = sqlalchemy_multitomulti.Author(name="jack") a3 = sqlalchemy_multitomulti.Author(name="Rain") b1.authors = [a1,a3] b2.authors = [a2,a3] b3.authors = [a1,a2,a3] session.add_all([b1,b2,b3,a1,a2,a3]) session.commit()

上面紅色標記是創建關聯關係,這樣創建出來以後,book_m2m_author表自動就會有數據。

固然若是咱們想要插入中文的書。即插入的數據有中文,咱們要怎麼作呢:

engine = create_engine("mysql+pymysql://root:root@192.168.123.207/xumingdb?charset=utf8",encoding='utf-8') Base = declarative_base()

 

須要在建立數據庫鏈接的時候在數據庫後面加上?charset=utf8

如今數據插入以後,最終要實現查詢數據:

1.查看做者xiaoming出版了多少本書:

author_obj = session.query(sqlalchemy_multitomulti.Author).filter(sqlalchemy_multitomulti.Author.name=="xiaoming").first() print(author_obj.books)

2.查看書b2是哪些做者出版的 :

book_obj = session.query(sqlalchemy_multitomulti.Book).filter(sqlalchemy_multitomulti.Book.id==2).first() print(book_obj.authors)

多對多刪除:

在刪除數據的時候咱們也一樣的不須要管book_m2m_author表,sqlalchemy會自動幫咱們把對應的數據刪除:

經過書刪除做者:

author_obj = session.query(sqlalchemy_multitomulti.Author).filter(sqlalchemy_multitomulti.Author.name=="xiaoming").first()
book_obj = session.query(sqlalchemy_multitomulti.Book).filter(sqlalchemy_multitomulti.Book.id==2).first()
book_obj.authors.remove(author_obj) session.commit()  

這個時候圖書2的關聯關係會自動少一個

 

直接刪除做者:

author_obj = session.query(sqlalchemy_multitomulti.Author).filter(sqlalchemy_multitomulti.Author.name=="xiaoming").first() session.delete(author_obj) session.commit()
相關文章
相關標籤/搜索