一.pymysql

  1.安装pymysql

    pip3 insatll mysql

  2.使用

#!/usr/bin/env python
# --*-- encoding:utf-8 --*--

import  pymysql

#创建连接
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='dbtwo')

#创建游标
cursor = conn.cursor()

#执行sql语句 插入
effect_row = cursor.execute("insert into tbone(nname,npwd) values('eee','eee')") 

#格式化字符串,插入
name = 'fff'
pwd = 'fff'
effect_row = cursor.execute("insert into tbone(nname,npwd) values(%s,%s)",(name,pwd))

#插入多条数据
effect_row = cursor.executemany("insert into tbone(nname,npwd) values(%s,%s)",[('abc','bcd'),('cde','def')])
#修改
effect_row = cursor.execute("update tbone set npwd ='111' where nname='eee'")
#删除
effect_row = cursor.execute("delete from tbone where nid=3") 

#提交数据 ,否则无法修改数据库
conn.commit()

#关闭游标
cursor.close()

#关闭连接
conn.close()

   3.查询数据

import pymysql

conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='dbtwo')
cursor=conn.cursor()
cursor.execute("select * from tbone")
#获取所有数据
res = cursor.fetchall()
#获取第一行数据
one = cursor.fetchone()
#获取前几行数据
many = cursor.fetchmany(3)

conn.commit()
cursor.close()
conn.close()

  注:在fetch数据时按照顺序进行,可以使用cursor.scroll(num,mode)来移动游标位置,如:

    cursor.scroll(1,mode='relative')  # 相对当前位置移动  当前位置跳过一个   可以为负数

    cursor.scroll(2,mode='absolute') # 相对绝对位置移动  从头开始跳过2个

  注:有多个结果集时:cursor.nextset() cursor.fetchall()

 

  4.默认的fetch函数获取的是元组类型((),(),()),想要获取字典类型[{},{},{}]:

      创建游标时,添加参数:cursor=conn.cursor(pymysql.cursors.DictCursor) 

  5.获取新增数据的自增ID

conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='dbtwo')
cursor=conn.cursor(pymysql.cursors.DictCursor)
effect_row = cursor.execute("insert into tbone(nname,npwd) values('ttt','ttt')")
#获取新增数据的最后一条自增ID
last_id = cursor.lastrowid
print(last_id)

conn.commit()
cursor.close()
conn.close()

 二 sql注入

  1.使用字符串拼接 ,会导致sql注入 : (数据库中的用户名:abc 密码:abc)

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#!/usr/bin/env python
# --*-- encoding:utf-8 --*--
import pymysql

conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='dbone')
cursor=conn.cursor(pymysql.cursors.DictCursor)
username=input('请输入用户名')
password=input('请输入密码')
sql_str = "select * from user where username = '%s' and password ='%s'"%(username,password)
cursor.execute(sql_str)
result = cursor.fetchone()
if result:
    print('登陆成功')
else:
    print('登陆失败')
conn.commit()
cursor.close()
conn.close()

View Code

  当用户名输入:abc' -- 

    sql:  select * from user where username = 'abc' -- ' and password ='123'  即可登陆成功 (-- 前后有空格)

  当用户输入 :sb' or 1=1 -- 

    sql :  select * from user where username = 'sb' or 1=1 -- ' and password ='sb'  也可登陆成功(-- 前后有空格)

  2.使用系统提供的函数,则不会导致sql注入

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#!/usr/bin/env python
# --*-- encoding:utf-8 --*--
import pymysql

conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='dbone')
cursor=conn.cursor(pymysql.cursors.DictCursor)
username=input('请输入用户名')
password=input('请输入密码')
cursor.execute("select * from user where username = %s and password =%s",(username,password))
result = cursor.fetchone()
if result:
    print('登陆成功')
else:
    print('登陆失败')
conn.commit()
cursor.close()
conn.close()

View Code

  注:字符串拼接要加 '%s'  ,系统提供的函数 %s  没有使用引号

 

三.SQLAlchemy

  SQLAlchemy是python的一个数据库ORM工具,提供了强大的对象模型间的转换,可以满足绝大多数数据库操作的需求,并且支持多种数据库引擎(sqlite,mysql,postgres, mongodb等),将对象转换为SQL语句,利用数据API执行SQL语句

  安装: pip install sqlalchemy

  

PyMySQL事务 pymysql sqlalchemy_数据_05

    SQLAlchemy本身无法操作数据库,其必须依赖pymsql等第三方插件,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

  1.内部处理

    使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from sqlalchemy import create_engine
  
  
engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", max_overflow=5)
  
# 执行SQL
# cur = engine.execute(
#     "INSERT INTO hosts (host, color_id) VALUES ('1.1.1.22', 3)"
# )
  
# 新插入行自增ID
# cur.lastrowid
  
# 执行SQL
# cur = engine.execute(
#     "INSERT INTO hosts (host, color_id) VALUES(%s, %s)",[('1.1.1.22', 3),('1.1.1.221', 3),]
# )
  
  
# 执行SQL
# cur = engine.execute(
#     "INSERT INTO hosts (host, color_id) VALUES (%(host)s, %(color_id)s)",
#     host='1.1.1.99', color_id=3
# )
  
# 执行SQL
# cur = engine.execute('select * from hosts')
# 获取第一行数据
# cur.fetchone()
# 获取第n行数据
# cur.fetchmany(3)
# 获取所有数据
# cur.fetchall()

View Code

  2.创建表

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#!/usr/bin/env python
# --*-- encoding:utf-8 --*--
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,UniqueConstraint,Index
from sqlalchemy.orm import sessionmaker

#连接数据库
engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/dbtwo?charset=utf8',echo=True)
#生成一个sqlorm 的基类
Base = declarative_base()

class User(Base):
    # 表名
    __tablename__ = 'userinfo'
    #字段
    aid = Column(Integer,primary_key=True)
    aname = Column(String(10),index=True)
    fullname = Column(String(10),unique=True)
    password = Column(String(10))
    contry = Column(String(10))
    address = Column(String(20))
    school = Column(String(10))
    grade = Column(String(10))
    #联合索引
    __table_args__ =(
        UniqueConstraint('contry','address',name='uni_contry_address'),
        Index('ind_sch_gra','school','grade')
    )

Base.metadata.create_all(engine)

创建表

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#!/usr/bin/env python
# --*-- encoding:utf-8 --*--
from  sqlalchemy.ext.declarative import  declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey,UniqueConstraint,Index
from sqlalchemy import  create_engine

engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/dbone",echo=True,max_overflow=5)

Base = declarative_base()
# 单表
class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    extra = Column(String(32))
    __table_args__ = (
        UniqueConstraint('id','name',name='uix_id_name'),
        Index('ix_id_name','name','extra')
    )
# 一对多
class Favor(Base):
    __tablename__ = 'favor'
    nid = Column(Integer,primary_key=True)
    caption = Column(String(50),default='red',unique=True)

class Person(Base):
    __tablename__ = 'person'
    nid = Column(Integer,primary_key=True)
    name = Column(String(32),index=True,nullable=True)
    favor_id = Column(Integer,ForeignKey('favor.nid'))

#多对多
class Group(Base):
    __tablename__='group'
    id = Column(Integer,primary_key=True)
    name = Column(String(64),unique=True,nullable=True)
    port = Column(Integer,default=10000)

class Server(Base):
    __tablename__ = 'server'
    id = Column(Integer,primary_key=True,autoincrement=True)
    hostname = Column(String(64),unique=True,nullable=False)

class ServerToGroup(Base):
    __tablename__ = 'servertogroup'
    nid = Column(Integer,primary_key=True,autoincrement=True)
    server_id = Column(Integer,ForeignKey('server.id'))
    group_id = Column(Integer,ForeignKey('group.id'))

def init_db():
    Base.metadata.create_all(engine)

def drop_db():
    Base.metadata.drop_all(engine)

一对多,多对多

 注:设置外键的另一种方式 ForeignKeyConstraint(['other_id'], ['othertable.other_id'])

  3.操作表(未定义__repr__,则返回的是类的对象)

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#!/usr/bin/env python
# --*-- encoding:utf-8 --*--

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,ForeignKey,UniqueConstraint,Index
from sqlalchemy.orm import sessionmaker,relationship
from sqlalchemy import create_engine


engine = create_engine('mysql+pymysql://root:root@127.0.0.1/dbthree',echo=True,max_overflow=5)
Base = declarative_base()
class Users(Base):
    __tablename__='user'
    id = Column(Integer,primary_key=True)
    name = Column(String(32))
    extra = Column(String(16))

    __table_args__=(
        UniqueConstraint('id','name',name='uni_id_name'),
        Index('in_name_extra','name','extra')
    )

    def __repr__(self):
        return "%s-%s"%(self.id,self.name)

#一对多
class Favor(Base):
    __tablename__='favor'
    nid = Column(Integer,primary_key=True)
    caption = Column(String(32),default='red',unique=True)

    def __repr__(self):
        return "%s-%s"%(self.nid,self.caption)

class Person(Base):
    __tablename__= 'person'
    nid = Column(Integer,primary_key=True)
    name= Column(String(32),index=True,nullable=True)
    favor_id = Column(Integer,ForeignKey('favor.nid'))
    #生成与表结构无关,仅便于查询
    favor  = relationship('Favor',backref ='pers')

#多对多
class ServerToGroup(Base):
    __tablename__ = 'servertogroup'
    nid = Column(Integer,primary_key=True,autoincrement=True)
    server_id = Column(Integer,ForeignKey('server.id'))
    group_id = Column(Integer,ForeignKey('group.id'))
    group = relationship('Group',backref='s2g')
    server = relationship('Server',backref='s2g')

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer,primary_key=True)
    name = Column(String(64),unique=True,nullable=True)
    port = Column(Integer,default=1000)
    # group = relationship('Group',secondary = ServerToGroup,backref='host_list')

class Server(Base):
    __tablename__='server'
    id = Column(Integer,primary_key=True,autoincrement=True)
    hostname= Column(String(64),unique=True,nullable=False)

def init_db():
    Base.metadata.create_all(engine)

def drop_db():
    Base.metadata.drop_all(engine)

# init_db()
Session = sessionmaker(bind=engine)
session = Session()

View Code

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#增
# obj = Users(name='aaa',extra='bbb')
# session.add(obj)
# session.add_all([
#     Users(name='a',extra='b'),
#     Users(name='b',extra='c')
# ])
# session.commit()

#删
# session.query(Users).filter(Users.id>2).delete()
# session.commit()

#改
# session.query(Users).filter(Users.id>1).update({'name':'ddd'})
# session.query(Users).filter(Users.id>1).update({Users.name:Users.name+"sb"},synchronize_session=False)
#修改id
# session.query(Users).filter(Users.id>1).update({'id':Users.id+1},synchronize_session='evaluate')
# session.commit()

# 查 :
# ret = session.query(Users).all() # __repr__() :[1-aaa, 3-dddsb]
# ret = session.query(Users.name,Users.extra).all()  # [('aaa', 'bbb'), ('dddsb', 'b')]
# ret = session.query(Users).filter_by(name='aaa').all()#   __repr__() :[1-aaa]
# ret = session.query(Users).filter_by(name='dddsb').first() # 3-dddsb

#其他查询
#条件
ret  = session.query(Users).filter_by(name='c').all()  #[5-c]
ret = session.query(Users).filter(Users.id>2,Users.name=='e').all() #[6-e]
ret = session.query(Users).filter(Users.id.between(5,7),Users.name=='g').all() #[7-g]
ret = session.query(Users).filter(Users.id.in_([3,4,5])).all() #[4-a, 5-c, 3-dddsb]
ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='e'))).all() #[6-e]
from sqlalchemy import and_,or_
ret = session.query(Users).filter(and_(Users.id>5),Users.name=='e').all() # [6-e]
ret = session.query(Users).filter(or_(Users.id< 3,Users.name=='aaa')).all() # [1-aaa]
ret = session.query(Users).filter(
    or_(
        Users.id < 3,
        Users.name =='aaa',
        Users.extra !=''
    )
).all()

#通配符
ret = session.query(Users).filter(Users.name.like('e%')).all() #[6-e]
ret = session.query(Users).filter(~Users.name.like('e%')).all() #[4-a, 1-aaa, 5-c, 3-dddsb, 7-g, 8-j]

# 限制
ret = session.query(Users)[3:4] # [3-dddsb]

#排序
ret = session.query(Users).order_by(Users.name.desc()).all()
ret = session.query(Users).order_by(Users.name.asc()).all()

#分组   分组时出现错误:sql_mode='NO_ENGINE_SUBSTITUTION'
from sqlalchemy.sql import func
# ret = session.query(Users.name).group_by(Users.name).all()
# ret = session.query(
#     func.max(Users.id),
#     func.sum(Users.id),
#     func.min(Users.id)
# ).group_by(Users.name).having(Users.id>2).all()


# 连表
ret = session.query(Users,Favor).filter(Users.id==Favor.nid).all()
ret = session.query(Person).join(Favor).all() # 返回的是Person 对象
ret = session.query(Person).join(Favor,isouter=True).all()


#组合
q1 = session.query(Users.name).filter(Users.id>2)
q2 = session.query(Favor.caption).filter(Favor.nid>2)
ret = q1.union(q2).all()

q1 = session.query(Users.name).filter(Users.id>2)
q2 = session.query(Favor.caption).filter(Favor.nid>2)
ret = q1.union_all(q2).all()
print(ret)

增删改查

  4.关联(relationship) 第三张表放在前面

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

# !/usr/bin/env python
# -*- coding:utf-8 -*-

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine

engine = create_engine(‘mysql+pymysql://root:123456@127.0.0.1:3306/kong‘)  # 连接已存在的数据库

Base = declarative_base()  # 根据SQL创建一个基类

class Son(Base):
    __tablename__ = ‘son‘

    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    age = Column(String(16))

    father_id = Column(Integer, ForeignKey(‘father.id‘))  # 外键(外键放在哪个类下,哪个就是多)

class Father(Base):
    __tablename__ = ‘father‘

    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    age = Column(String(16))

    son = relationship(‘Son‘)  # 是取与son关联的数据(通过父关联子找)
    # son = relationship(‘Son‘, backfe="father")  # backfe="father"是(“backfe”是关键字通过子关联父找)

Base.metadata.create_all(engine)  # 创建所有的表
# Base.metadata.drop_all(engine)  # 删除表

Session = sessionmaker(bind=engine)
session = Session()
f1 = Father(name=‘alvin‘, age=50)
# session.commit()
w1 = Son(name=‘little alvin1‘, age=4)
w2 = Son(name=‘little alvin2‘, age=5)
w3 = Son(name=‘little alvin3‘, age=5)
f1.son = [w1, w2, w3]


session.add_all([f1, w1, w2])
session.commit()

一对多

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine

engine = create_engine(‘mysql+pymysql://root@127.0.0.1:3306/kong‘)

Base = declarative_base()


class Son(Base):
    __tablename__ = ‘son‘
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    age= Column(String(16))

    father_id=Column(Integer,ForeignKey(‘father.id‘))  # 外键关系,关联两张表的关系(下面的关联查询)


class Father(Base):
    __tablename__ =‘father‘

    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    age= Column(String(16))
    
    son=relationship(‘Son‘,backref=‘father‘)  # 相当于在father类下写father=relationship(‘father‘)和在son类下写son=relationship(‘son‘)一样的效果
                                              # 通过儿子关联并找父亲的信息;通过父亲关联并找儿子的信息(这就是relationship的关系)

Base.metadata.create_all(engine)
# Base.metadata.drop_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# ret=session.query(Father.name.label(‘kkk‘),Son.name.label(‘ppp‘)).join(Son)  # (关联查询)关联儿子并拿出所有的符合条件的数据
# print(ret)                                # Son.name.label(‘ppp‘)) 是给son.name起一个名字;label是关键字

#f1=session.query(Father).filter_by(id=1).first()  # 查询父亲的信息
# print(f1.son)
# s1=session.query(Son).filter_by(id=2).first()  # # 查询儿子的信息;filter_by是键值对形式的查询;filter是条件的形式查询
# print(s1.father.name,s1.name)

f1=session.query(Father).filter_by(id=1).first()  # 不加first这类的索引只能得到sql语句不能得到具体的数据。
w4=Son(name=‘little alvin4‘,age=5)  # 创建一条数据(这就是relationship内部帮实现的)
f1.son.append(w4)  # 插入这一条信息


session.add(f1)
session.commit()

关联查询

PyMySQL事务 pymysql sqlalchemy_sqlalchemy

PyMySQL事务 pymysql sqlalchemy_PyMySQL事务_02

# !/usr/bin/env python
# -*- coding:utf-8 -*-


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

engine = create_engine(‘mysql+pymysql://root:123456@127.0.0.1:3306/kong?charset=utf8‘)  # 连接已存在的数据库; 插入汉子就要添加编码解析?charset=utf8

Base = declarative_base()  # 根据SQL创建ORM的基类

class Men_to_Wemon(Base):
    __tablename__ = ‘men_to_wemon‘
    nid = Column(Integer, primary_key=True)
    id = Column(Integer, primary_key=True)
    men_id = Column(Integer, ForeignKey(‘men.id‘))
    women_id = Column(Integer, ForeignKey(‘women.id‘))

class Men(Base):
    __tablename__ = ‘men‘
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    age = Column(String(16))
    # gf = relationship("Women", secondary=Men_to_Wemon.__table__)  # 可以在下面的backref=‘gf‘替代,表示关联;
                                                                    # secondary如果有第三张表会自动关联必须加__table__,

class Women(Base):
    __tablename__ = ‘women‘
    id = Column(Integer, primary_key=True)
    name = Column(String(32))
    age = Column(String(16))
    bf = relationship("Men", secondary=Men_to_Wemon.__table__, backref=‘gf‘)

Base.metadata.create_all(engine)  # 在数据库生成表
Session = sessionmaker(bind=engine)  # 通过激活sessionmaker的__call__方法来return一个Session实例(Session类下提供了增删改查的具体方法)
session = Session()

# 下面是插入数据
# m1 = Men(name=‘alex‘, age=18)
# m2 = Men(name=‘wusir‘, age=18)
# w1 = Women(name=‘如花‘, age=26)
# w2 = Women(name=‘铁蛋‘, age=30)
# session.add_all([m1, m2, w1, w2])
# session.commit()  # 提交添加的数据

# t1 = Men_to_Wemon(men_id=1, women_id=2)  # 第三张表,让之前的两张表创建一个对应关系



m1 = session.query(Men).filter_by(id=2).first()  # 查询Men的信息是(列表)
w1 = session.query(Women).all()  # 查询Women的信息是(列表)
m1.gf = w1  # 让查询的信息创建关系

session.add_all([m1])
session.commit()

# 需要注意的地方:
#    1 查询时如果不加all,first等,得到的是sql语句,加上后,才是具体的结果;而all的结果是一个列表。
#    2 m1.gf是一个列表,里面存放着符合条件的对象。
#    3 filter与filter_by的区别:filter是拿键值对的参数,filter_by是拿条件判断的参数。

多对多