无聊顺便把慕课的操作三大数据库看了
链接贴上: https://coding.imooc.com/class/chapter/507.html
三大常见的数据库,每次去操作要去翻看文档就很烦
然后就简单写了几个实战的脚本,看代码就知道该怎么做了
因为情况很多,万变不离其中,我就没封装成面向对象
(一部分是要考虑很多种情况,其次是相当于复习加固就是懒得写)
今天先发Mysql的,因为其他的我还在写~
首发于 https://sleepymonster.cn
其实最主要的是会用%s写数据进去 我记得原来往数据库里面写图片来着 转了格式 最后用%s写进入的
$ pip install mysql-connector-python
$ pip install mariadb
$ pip install mysqlClient
$ pip install PyMySQL # 这个是主要使用的
from pymysql import connect, Error
from pymysql.cursors import DictCursor
# 建立连接
# 返回的是一个对象
try:
connect = connect(
host='127.0.0.1',
port=3306,
user='root',
password='',
database='go_gateway_test',
cursorclass=DictCursor # 是否开启以字典的形式返回(不要这行就是元组)
)
with connect: # 在with下会自动关闭免去connect.close
with connect.cursor() as cursor: # 建立游标
sql = 'SELECT * From gateway_service_info;'
cursor.execute(sql) # 执行sql语句
# 获取查询结果
for each in cursor:
print(each) # (34, 0, 'websocket_test', 'websocket_test', 1)
# 检索一条数据
oneData = cursor.fetchone()
print(oneData)
another = cursor.fetchone() # 会在上面的基础上继续取
print(oneData)
# 检索全部
allData = cursor.fetchall()
for each in allData:
print(each)
# 检索指定数量的数据
dataList = cursor.fetchmany(10)
for each in dataList:
print(each)
# 防止造成sql注入 采用%s的形式写入
sql = "SELECT * From gateway_service_info where id = %s"
cursor.execute(sql, (34,))
for each in cursor:
print(each)
# 修改操作
sql = "UPDATE gateway_service_info SET load_type = 1 where id = 34;"
cursor.execute(sql)
connect.commit() # 必须要提交事务
# 插入操作
load_type = 1
service_name = 'ServiceName'
sql = "INSERT INTO `gateway_service_info`(`load_type`, `service_name`) VALUES (%s, %s)"
cursor.execute(sql, (load_type, service_name))
connect.commit() # 必须要提交事务
# 批量插入
# sql语句的构造我这里就不写了
sql1 = "INSERT INTO `gateway_service_info`(`load_type`, `service_name`) VALUES (1, 'ServiceName1')"
sql2 = "INSERT INTO `gateway_service_info`(`load_type`, `service_name`) VALUES (2, 'ServiceName2')"
connect.begin() # 开始事务
try:
cursor.execute(sql1)
cursor.execute(sql2)
connect.commit()
except Exception as e:
connect.rollback() # 出现错误,开始回滚
# 删除
sql = "DELETE FROM gateway_service_info WHERE id = %s"
cursor.execute(sql)
connect.commit() # 必须要提交事务
# 批量增加
sql = "INSERT INTO `gateway_service_info`(`load_type`, `service_name`) VALUES (%s, %s)"
args = ((1, "ServiceName"), (2, "ServiceName"))
cursor.executemany(sql, args)
except Error as e:
print('连接失败:{}'.format(e))
直接用的面向对象的思想,减少SQL语句的书写
下面我直接拆开(怕是GORM一家人)都是能跑的
大部分意思我都写再了注释里面,从上往下看基本都能掌握,没啥弯弯绕绕的
$ pip install SQLAlchemy
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Enum, SmallInteger, Boolean, ForeignKey, \
select, func, update, delete
from sqlalchemy.orm import declarative_base, relationship, backref, Session
from sqlalchemy.types import CHAR
from sqlalchemy.dialects.mysql import TINYINT
from datetime import datetime
from enum import IntEnum
# 声明一个连接
userName = 'root'
password = ''
host = '127.0.0.1'
port = 3306
database = 'go_gateway_test'
engine = create_engine(f'mysql+pymysql://{userName}:{password}@{host}:{port}/{database}?charset=utf8', echo=True, future=True)
# 声明ORM的一个基类并建立映射关系
Base = declarative_base()
class SexEnum(IntEnum):
MAN = 1
WOMEN = 2
# name为在数据库表中的名称
# type为数据类型
# comment为注释
# nullable为不能为空
# default为默认字段
# unique为唯一约束
class User(Base):
"""用户信息表格"""
__tablename__ = 'account_user'
id = Column(Integer, name='id', primary_key=True)
user_name = Column(String(32), nullable=True, name='user_name', comment="user_name", unique=True)
password = Column(String(512), nullable=True, name='password', comment="password")
real_name = Column(String(16), nullable=False, name='real_name', comment="real_name")
sex = Column(Enum(SexEnum), default=None, name='sex', comment="sex")
age = Column(TINYINT(unsigned=True), default=0, name='age', comment="age")
create_at = Column(DateTime, default=datetime.now(), name='create_at', comment="create_at")
is_valid = Column(Boolean, default=True, name='is_valid', comment="is_valid")
profile = relationship('UserProfile', backref='user', uselist=False) # 一对一
class UserAddress(Base):
"""地址信息表格"""
__tablename__ = 'account_user_address'
id = Column(Integer, name='id', primary_key=True)
area = Column(String(256), nullable=False, name='area', comment="area")
phone_num = Column(CHAR(11), name='phone_num', comment="phone_num")
remark = Column(String(512), name='remark', comment="remark")
is_valid = Column(Boolean, default=True, name='is_valid', comment="is_valid")
create_at = Column(DateTime, default=datetime.now(), name='create_at', comment="create_at")
# user_id = Column(Integer, ForeignKey(User.id), comment="关联") # 进行ORM关联一对多
user_id = Column(Integer, ForeignKey(User.id, ondelete="CASCADE"), comment="关联") # 进行ORM关联一对多,操作一:指定删除后操作
# user = relationship("User", backref='address') # 一对多经典
# user = relationship("User", backref=backref('address', lazy='dynamic')) # 可以执行子查询
user = relationship("User", backref=backref('address', lazy='dynamic', cascade="all,delete")) # 可以执行子查询 操作二:指定删除后操作
class UserProfile(Base):
"""用户详细信息表格"""
__tablename__ = 'account_user_profile'
id = Column(Integer, primary_key=True)
hobby = Column(String(255), nullable=False, name='hobby', comment="hobby")
user_id = Column(Integer, ForeignKey(User.id), comment="user_id")
# user = relationship("User", backref=backref('profile', unelist=False)) # 两种方法
# 同步关系创建/删除数据库
# Base.metadata.create_all(engine) # 创建表
# Base.metadata.drop_all(engine) # 删除表
# 新增数据
# 构建一个对象
userObj = User(
user_name='Jack' + str(datetime.now()),
password='123456',
real_name='杰克',
sex=1
)
# 添加到session
session = Session(bind=engine, future=True)
session.add(userObj) # 添加一个
# session.add_all([userObj, userObj]) # 添加多个
session.commit()
# 这个部分有点难 理清楚顺序
# 根据一对一,一对多的关系添加数据
# 首先是创建主表的一份数据
userObj = User(
user_name='Rose' + str(datetime.now()),
password='123456',
real_name='肉丝',
sex=2
)
# 一个人可以对应多个地址
userObj.address.append(
UserAddress(user=userObj, area="地址01", phone_num="11111111111")
)
userObj.address.append(
UserAddress(user=userObj, area="地址02", phone_num="11111111111")
)
session.add(userObj) # 添加这个人的时候同时会添加2份数据
profile = UserProfile(user=userObj, hobby='宝石') # 一对一的详细信息
session.add(profile)
session.commit() # 在提交之前会自动进行回滚 如果使用 session.begin() session.rollback()
session.close()
# 根据用户ID查询信息(根据主键进行查询)
idIndex = 1
session = Session(bind=engine, future=True)
userObj = session.get(User, idIndex) # 根据主键进行查询
userObjDetail = '{} => {}'.format(userObj.user_name, userObj.real_name)
# 使用select查询全部/第一个
stmt = select(User)
rows = session.execute(stmt) # 要全部
maps = session.execute(stmt).mappings() # 返回的是字典
rowOnlySome = session.execute(select(User.id, User.user_name)) # 只要指定的几个字段
rowOne = session.execute(stmt).fetchone() # 只要第一个
rowStillOne = session.execute(stmt).scalars().first() # 只要第一个且为ORM的实体对象
# 使用SQLAlchemy进行条件查询
# 使用where条件查询
# User.id > 12
# User.id.between(8,12)
# User.id.is_(None)
# User.id.is_not(None)
# User.id.in_((9, 12))
# or_(User.id == 9, User.id == 12)
# User.id.like("Hello%")
# User.id.like("Hello_")
# where(xxxx).where(xxxx)可以连续或者and_(User.id == 9, User.password == 123456)
# or_(and_(User.id == 9, User.password == 123456), and_(User.id == 9, User.password == 123456)) # 并集
stmt = select(User).where(User.id == 1)
rowWhere = session.execute(stmt).scalar_one_or_none() # 没有就返回None
# 函数的使用
stmt = select(func.count().label("total")).select_from(User)
row = session.execute(stmt).mappings().one() # 字典的形式访问
total = session.query(User).filter(User.id > 10).count() # 使用query
stmt = select(func.max(User.id).label("max_id"), func.min(User.id).label("min_id")).where(User.password == 123456)
maxAndMin = session.execute(stmt).mappings().one()
# 多表查询
# 由上取下面的数据
user = session.get(User, 24)
addList = user.address
areas = [each.area for each in addList]
# 由下面取上面的数据
address = session.get(UserAddress, 23)
userInfo = address.user
# 因为开启了lazy可以进一步筛选
newAddList = addList.filter(UserAddress.id > 1)
# 分组与去重
# having()是一样的
stmt = select(User.password).distinct()
res = session.execute(stmt).scalars().all()
stmt = select(User.sex, func.count().label("total")).group_by(User.sex)
resTotal = session.execute(stmt).mappings().all()
# 排序与分页
# order_by(xxxx.desc()) # 倒序
# order_by(desc(label)) # 如果有新创建标签则可以这样
# offset()是偏移量的意思
# limit()是限制多少的意思
# 两者联合使用就可以产生分页的效果
# 注意: 从11-20则偏移量为10
# 修改数据
# 修改单条信息
# 拿到对应的-》修改属性-》添加进入-》提交事务
oneObj = session.get(User, 10)
oneObj.password = 123789
session.add(oneObj)
session.commit()
# 批量修改
# stmt = update(User).where(User.id < 10).values(password=User.password + 1)
stmt = update(User).where(User.id < 10).values(password=User.password + 1).execution_options(
synchronize_session="fetch") # 修改同步策略
resInfo = session.execute(stmt) # 执行
session.commit() # 提交
print(resInfo.rowcount) # 查看受影响的行数
# 删除数据
# 删除单条数据
# 拿到对应-》删除-》提交
oneObj = session.get(User, 11)
session.delete(oneObj)
session.commit()
# 连着关联信息删除
# 对应的Column上要改 relation上也要改
# 多时用的是软删除
# 批量删除
# 删除时候指定条件-》执行-》提交
stmt = delete(User).where(User.id > 100)
resInfo = session.execute(stmt)
session.commit()
print(resInfo.rowcount) # 查看受影响的行数