1.MySQL
MySQL是一个关系型数据库管理系统不同于非关系型的redis。
- 特点:
- 使用c和c++编写,并使用多种编译器测试,保证了源代码的可移植性,支持多种操作系统。
- 为多种编程语言提供了API。支持多线程,充分利用CPU资源
- 优化SQL查询算法,有效提高查询速度
- 提供多语言支持,常见的编码如GB2312、UTF-8
- 提供TCP/IP、 ODBC和JDBC等多种数据库连接途径
- 提供用于管理数据库操作的管理工具
- 支持多种存储引擎,并且采用了GPL协议,你可以修改源码来开发自己的Mysql系统
- 在线DDL更改功能
- 复制全局事务标识,无崩溃从机、多线程从机
2.SQLAlchemy的使用
- 数据库是一个网站的基础,在flask框架中,可以通过ORM来操作数据库使其更加简单。
2.1通过SQLAlchemy连接数据库
from sqlalchemy import create_engine
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'sqlalchemy'
USERNAME = 'root'
PASSWORD = 'root'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
# 创建数据库引擎
engine = create_engine(DB_URI)
#创建连接
with engine.connect() as con:
result = con.execute('select * from students')
print(result.fetchone())
- 注意:create_engine函数创建数据库引擎,需要满足对字符串描述的字符串格式。
dialect+driver://username:password@host:port/database?charset=utf8
#dialect:数据库的实现,例如上面的mysql,
#driver是Python对应的驱动,如果不指定,默认选择驱动,如上面指定的pymysql。
2.2SQLalchemy执行原生的SQL
代码示例:
from sqlalchemy import create_engine
HOSTNAME = '127.0.0.1'
DATABASE = 'flask_sqlalchemy'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
#连接数据库
engine = create_engine(DB_URI,echo=True)
# 使用with语句连接数据库,如果发生异常会被捕获
with engine.connect() as con:
# 先删除users表
con.execute('drop table if exists authors')
# 创建一个users表,有自增长的id和name
con.execute('create table authors(id int primary key auto_increment,'name varchar(25))')
# 插入两条数据到表中
con.execute('insert into persons(name) values("abc")')
con.execute('insert into persons(name) values("xiaotuo")')
# 执行查询操作
results = con.execute('select * from persons')
# 从查找的结果中遍历
for result in results:
print(result)
2.3使用SQLalchemy-ORM框架
- ORM:Object Relationship Mapping对象关系映射,通过ORM可以使用类的方式去操作数据库,无需自己写原生的SQL语句,ORM会在执行操作的时候将其转化为对应的数据库原生语句。
- ORM优点:
- 易用性:有效的减少SQL语句,使得模型更加直观
- 性能损耗少,轻松写出复杂的查询语句。
- 可移植性:SQLalchemy封装了底层的数据库实现,支持多个关系型数据库,包括MySQL等等。
- 使用ORM操作数据库,首先创建一个类来映射对应的表。例如创建含有下面的几个字段的表
from sqlalchemy import Column,Integer,String#需要导入几个相应的字段。
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
HOSTNAME = '127.0.0.1'
DATABASE = 'flask_sqlalchemy'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
engine = create_engine(DB_URI,echo=True)
# 所有的类都要继承自`declarative_base`这个函数生成的基类
Base = declarative_base(engine)
class User(Base):
# 定义表名为users
__tablename__ = 'users'
# 将id设置为主键,并且默认是自增长的
id = Column(Integer,primary_key=True)
# name字段,字符类型,最大的长度是50个字符
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
# 让打印出来的数据更好看,可选的
def __repr__(self):
return "<User(id='%s',name='%s',fullname='%s',password='%s')>" % (self.id,self.name,self.fullname,self.password)
Base.metadata.create_all()#只有执行了该语句,才能将其映射到数据库中,创建User表格
#插入数据到数据库里
Session = sessionmaker(bind=engine)
session = Session()
user = User(name='dk', fullname='duke', password='dgd')
session.add(user)#此时只是讲数据添加到session对象里,并没有存储到数据库里,因此需要提交。
session.commit()#提交数据到数据库里
print(user.id)
print(user.name)打印数据
- 在没有做commit操作时,操作都是在事务中完成,因此这里就有回滚的可能操作,如下:
# 修改user的用户
user.name = '杜克'
# 创建一个新的用户
user1 = User(name='fakeuser',fullname='Invalid',password='12345')
# 将新创建的user1添加到session中
session.add(user1)
# 判断`user1`是否在`session`中存在
print(user1 in session)
# 从数据库中查找name=杜克的用户
data = session.query(User).filter_by(name='杜克')
print(data)
# 打印出查找到的data对象,注意这个对象的name属性已经在事务中被修改为杜克了。
> <User(name='杜克', fullname='duke', password='dgd')>
# 刚刚所有的操作都是在事务中进行的,现在来做回滚操作
session.rollback()
print(data)
# 再看user1是否还在session中
print(user1 in session)#false
2.4利用query对数据库的数据进行查询
- 查找的操作都是通过session.query()方法实现,Query对象相当于一个数组装载了数据,并且可以进行迭代。
- 向query里传递类,那么提取的数据就是类的实例。
data = session.query(User).all()#如果不加all(),输出的就是原生的SQl语句
for i in data
print(i)
- 向query里传递的是ORM类的属性,查找出来的就是元组
data = session.query(User.name).all()#如果不加all(),输出的就是原生的SQl语句
for i in data:
print(i)
- 向query传递的数据是两个或者多个对象,查找的也是元组
data= session.query(User.fullname, User.name).all()#如果不加all(),输出的就是原生的SQl语句
for i in data():
print(i)
- 可以对查询结果进行切片操作
data= session.query(User.fullname, User.name).order_by(User.id)[1:3].all()
for i in data():
print(i)
2.5sqlalchemy常用数据类型
Integer:整形。
Float:浮点类型。
Boolean:传递True/False进去。
DECIMAL:定点类型。
enum:枚举类型。
Date:传递datetime.date()进去。 2020 10 28
DateTime:传递datetime.datetime()进去。 2020 10 28 21 36 21
Time:传递datetime.time()进去。 21 36 21
String:字符类型,使用时需要指定长度,区别于Text类型。
Text:文本类型。
LONGTEXT:长文本类型。
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DECIMAL, Boolean, Enum, DATE, DATETIME, Time, Text
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import sessionmaker
from datetime import datetime
import random
from sqlalchemy import func
HOSTNAME = '127.0.0.1'
DATABASE = 'flask_demo'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
engine = create_engine(DB_URL)
# 都要继承函数生成的基类
Base = declarative_base(engine)
"""
Integer:整形。
Float:浮点类型。
Boolean:传递True/False进去。
DECIMAL:定点类型。
enum:枚举类型。
Date:传递datetime.date()进去。 2020 10 28
DateTime:传递datetime.datetime()进去。 2020 10 28 21 36 21
Time:传递datetime.time()进去。 21 36 21
String:字符类型,使用时需要指定长度,区别于Text类型。
Text:文本类型。
LONGTEXT:长文本类型。
"""
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), nullable=False)
price = Column(DECIMAL(20, 2))#DECIMAl表示保留小数点后几位
def __str__(self):
return 'User(name:{}, price:{})'.format(self.name, self.price)
# Base.metadata.drop_all()
# Base.metadata.create_all()
Session = sessionmaker(bind=engine)
session = Session()
# for i in range(6):
# user =User(name='lihua%s'% i, price=random.randint(1,100))
# session.add(user)
#
# session.commit()
users = session.query(User).all()
print(users)
for user in users:
print(user)
#聚合函数的使用方法
# result = session.query(func.avg(User.price)).all()
# print(result)
#query常用的聚合函数
"""
func.count:统计行的数量。
func.avg:求平均值。
func.max:求最大值。
func.min:求最小值。
func.sum:求和。
"""
- Column常用的参数
default:默认值。 当你设置了default=xxx的时候,你如果没有传递这个数据,那么数据库会显示你设置的这个值
nullable:是否可空。 nullable=False 表示不能为空
primary_key:是否为主键。
unique:是否唯一。 当你设置了这个参数的时候,那么同一列的数据不能相同,相同就报错
autoincrement:是否自动增长。
onupdate:更新的时候执行的函数。
name:该属性在数据库中的字段映射
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DECIMAL, Boolean, Enum, DATE, DATETIME, Time, Text
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import sessionmaker
from datetime import datetime
HOSTNAME = '127.0.0.1'
DATABASE = 'flask_demo'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
engine = create_engine(DB_URL)
Base = declarative_base(engine)
"""
Integer:整形。
Float:浮点类型。
Boolean:传递True/False进去。
DECIMAL:定点类型。
enum:枚举类型。
Date:传递datetime.date()进去。 2020 10 28
DateTime:传递datetime.datetime()进去。 2020 10 28 21 36 21
Time:传递datetime.time()进去。 21 36 21
String:字符类型,使用时需要指定长度,区别于Text类型。
Text:文本类型。
LONGTEXT:长文本类型。
"""
class Language(Base):
__tablename__ = 'langauages'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50))
price = Column(DECIMAL(20, 5))
is_delete = Column(Boolean)
# 枚举
gender = Column('sex', Enum('男', '女'))
create_time = Column(DATETIME)
content = Column(LONGTEXT)
update_time = Column(DATETIME, onupdate=datetime.now())
Base.metadata.drop_all()
Base.metadata.create_all() # 映射完一次后就可以注释掉,不然会不断的重新映射
Session = sessionmaker(bind=engine)
session = Session()
language = Language(name='ruby', price=10.123, is_delete=False, gender='男',create_time=datetime(2020, 12, 28, 17, 32, 30), content='safasvaesfaca', update_time=None)
session.add(language)
data = session.query(Language).first()
data.name = 'java'
session.commit()
- filter_by和filter过滤条件
all()#输出数据库所有数据
first()#输出满足条件的第一条数据
get(2)#获取第二条数据
filter 和 filter_by过滤
# 第一种:使用filter_by过滤:传入的是关键字参数
for name in session.query(User.name).filter_by(fullname='duke'):
print(name)
# 第二种:使用filter过滤:传入的是条件判断更加灵活
for name in session.query(User.name).filter(User.fullname=='duke'):
print(name)
from sqlalchemy import create_engine, and_, or_
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DECIMAL, Boolean, Enum, DATE, DATETIME, Time, Text
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import sessionmaker
from datetime import datetime
import random
from sqlalchemy import func
HOSTNAME = '127.0.0.1'
DATABASE = 'flask_demo'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
engine = create_engine(DB_URL)
Base = declarative_base(engine)
class Book(Base):
__tablename__ = 'books'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), nullable=False)
price = Column(DECIMAL(20, 2))
def __str__(self):
return 'Book(name:{}, price:{})'.format(self.name, self.price)
Base.metadata.drop_all()
Base.metadata.create_all()
Session = sessionmaker(bind=engine)
session = Session()
for i in range(6):
book =Book(name='西游记%s'% i, price=random.randint(1,100))
session.add(book)
session.commit()
# eq 相等
# result = session.query(Book).filter(Book.name == '西游记1').all()
# not eq 不相等
# result = session.query(Book).filter(Book.name != '西游记1').all()
#模糊查询 like
# result = session.query(Book).filter(Book.name.like('%西%') ).all()
# in 在什么里面
# result = session.query(Book).filter(Book.name.in_(['西游记1', '西游记3'])).all()
# not in 或者加~
# result = session.query(Book).filter(Book.name.notin_(['西游记1', '西游记3'])).all()
# null None ,没有占位置 为空 相等于空的字符串,占了位置
# result = session.query(Book).filter(Book.name == None).all()
# result = session.query(Book).filter(Book.name.is_(None)).all()
# is not null
# result = session.query(Book).filter(Book.name.isnot(None)).all()
# result = session.query(Book).filter(Book.name != None).all()
# and 联合查询的3种写法
# result = session.query(Book).filter(Book.name == '西游记1', Book.price == '68.00').all()
# result = session.query(Book).filter(and_(Book.name == '西游记1', Book.price == '68.00')).all()
# result = session.query(Book).filter(Book.name=='西游记1').filter(Book.price==68.00).all()
# or
result = session.query(Book).filter(or_(Book.name == '西游记2', Book.price == '14.00')).all()
# print(result)
for d in result:
print(d)