老男孩14期自动化运维day12随笔和作业

1.关系型数据库

Oracle 收费
Mysql 开源 被oracle收购了
SqlServer 微软
DB2 IBM
Postgresql
Sqlite 轻量级
access 轻量级

2.基本sql操作就不写了 看博客

(1)讲下外键:

建立外键 外键约束

KEY ‘key_name’(‘class_id’), CONSTRAINT ‘key_name’ FOREIGN KEY
(‘class_id’) PREFERENCES ‘class’ (‘id’)

key_name 可写可不写

mysql 默认不匹配大小写

(2)mysql连接查询

mtysql 连接查询

inner join (内连接、等值连接):获取两个表中字段匹配关系的记录 left
join(外连接,左连接):获取左表所有记录,即使右边没有匹配的字段 right
join(外连接,右连接):获取右边所有记录,即使左边没有匹配的字段

(3)事务

只有使用了InnoDB作为存储引擎才支持事务

四个特性(ACID):Atomicity 原子性,Consistency 稳定性,Isolation 隔离性,Durability 可靠性

详情见博客
<< begin;
<< insert …
<< rollback 没有begin开始事务就不能回滚

(4)索引

数据库索引:可以先理解为相当于每个字段都hash() 然后哈希值排序,最后二分查找(B树),时间复杂度O(log n),比如42亿个数据
为2^32,最多32次, 这是B树,但是磁盘IO消耗太大了,所以数据库采用的是B+树,是改良的B树(B-tree 或者B-树
但是其实这样叫不准确 容易误导),类似二分查找

索引分单列索引和组合索引。

单列索引:即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引
组合索引:即一个索引包含多个列(在两个字段加起来时才唯一的时候,可以做组合索引,如果两个字段有一个唯一就没必要)

创建索引是应用SQL查询语句的条件(一般WHERE子句的条件)

索引的缺点。。见博客

主键是一种索引,默认的

普通索引创建方式:

查看索引:show index from table
创建索引:create index index_name on table(column(32))
修改索引:alter table add index index_name on (column(32))
删除索引:drop index index_Name on table

唯一索引创建方式:
与上面类似,不同的事索引列的值必须唯一,但允许有空值。
就在上面index 前加 unique

更多见博客

3.python操作mysql

MYSQLdb 在3.0上用不了,因为没更新
3.0用pymysql 与MYSQL语句一样

execute() 单个执行
executemany() 批量插入

import pymysql

# 创建连接
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='960314',db='app_version')
# 创建游标,类似mysql终端上的游标
cursor = conn.cursor()

# 执行SQL,返回值是受影响行数

effect_row=cursor.execute("select * from sys_log ")

# print(effect_row)

print(cursor.fetchone()) # 取一条
print(cursor.fetchmany(3)) # 取前三条
# print(cursor.fetchall())
#  取所有,如果没有前面那个取一条,就把所有的取了,如果前面取了多少,就从上次取的地方开始取


# 批量提交
# li =[
#      ('alex','usa'),
#      ('sb','usa'),
# ]
# reCount = cur.executemany('insert into UserInfo(Name,Address) values(%s,%s)',li)
#
# conn.commit() 默认已经变成了事务 所以要提交,不然不会修改
# cur.close()

4.ORM框架 sqlalchemy

ORM框架(Object-Relational-Mapping) 对象关系映射

python下最著名的ORM框架 SQLAlchemy
用户 openstack,uber等

注意一个小点:

要想写中文 在 engine =create_engine(“mysql+pymysql://root:960314@localhost/pytest”,encoding=‘utf-8’,echo=True) 写了encoding还不管用
必须要写成“mysql+pymysql://root:960314@localhost/pytest?charset=utf8”
以后就直接写“mysql+pymysql://root:960314@localhost/pytest?charset=utf8” 不用写encoding了

使用sqlalchemy流程:

1.engine=create_engine(url…)
2.Base=declarative_base()
3.-----------建表---------------
一般建表法(常用):

class User(Base):
_ tablename _=‘user’ # 表名
id = Column(Integer,primary_key=True)
name = Column(String(32))
password = Column(String(64))

不通过类的建表法(少用,一般在建立用户不用关心的中间表时使用):

book_m2m_author = Table(‘book_m2m_author’, Base.metadata,
Column(‘book_id’,Integer,ForeignKey(‘books.id’)),
Column(‘author_id’,Integer,ForeignKey(‘authors.id’)),
)

4.Base.metadata.create_all(engine)
------------创建数据------------
5.Session_class=sessionmaker(bind=engine) 注意 这里是创建了一个类
6.session=Session_class() 实例化
7.user_obj = User(name=‘yang’,password=‘960314’) 创建数据对象
8.session.add_all([user_obj]) 把数据对象列表作为对象传入
9.seesion.commit() 提交 不提交不会生效

-----------查询数据--------------
filter_by()

10.data=Session.query(User).filter_by(name=‘yang’).all() all是所有 是生成一个列表
11.data=Session.query(User).filter_by(name=‘yang’).first() 是生成一个对象

filter() 最好用filter

12.data=Session.query(User).filter(name==‘yang’).all() all是所有 是生成一个列表
13.data=Session.query(User).filter(name==‘yang’).first() 是生成一个对象

update 查百度

(1)ORM基本写法

import sqlalchemy


'''ORM框架基本写法'''
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:960314@localhost/pytest",
                      encoding='utf-8',echo=True) # echo=True 打印所有信息
# sqlalchemy 底层也是mysqld、pymsql、oracle等的封装

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) # 创建表结构 把base下所有子类都创建了

# 创建数据
Session_class=sessionmaker(bind=engine) # 创建与数据库的会话session class,注意,这里返回给session的是个类,不是一个实例
Session=Session_class() # 生成session 实例

# 插入数据
# user_obj = User(name='yang',password='960314') # 生成你要创建的数据对象
# user_obj2 = User(name='hape',password='123456')
# print(user_obj.name,user_obj.id) # 此时还没创建对象,id还是none
#
# Session.add(user_obj) # 把要创建的数据对象添加到这个session里,一会统一创建
# Session.add(user_obj2)


# 查询数据
#data=Session.query(User).filter_by(name='yang').all() # 所有数据取成一个列表
data=Session.query(User).filter(User.id<10).filter(User.id>3).all() # 多条件查询
# filter_by不好用就用filter

print(data)  # data是一个装对象的列表
print(data[0].name,data[0].password)
Session.commit() # 现在才统一提交,创建数据


# Session.rollback() 回滚

(2)外键写法


'''建立外键'''
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:960314@localhost/pytest",
                      encoding='utf-8',echo=True)

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 "<%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") # 这个nb,允许你在student表里通过backref 字段反向查出所有它在student_recprd里的信息,也可以反查
    # ORM将两个对象关联起来,互相调用,在内存里的关联关系而不是数据库
    # 注意!!!relationship的第一个参数是类!!!比如说上面的Student类!!
    # 上面相当于 student=query(Student).filter(Student.id==stu_obj.stu_id.first())
    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()
#
# s1 = Student(name="yang",register_date="2018-12-03")
# s2 = Student(name="lisi",register_date="2016-12-03")
# s3 = Student(name="zhangsan",register_date="2017-12-03")
# s4 = Student(name="wangwu",register_date="2018-09-03")
#
# 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([study_obj1,study_obj2,study_obj3,study_obj4])

name_List=[]
stu_obj=session.query(Student.name,Student.id).all() # first()是一个对象 list()是一个对象的列表
for i in range(len(stu_obj)):
    name_List.append(stu_obj[i][0]+",id:"+str(stu_obj[i][1]))
print(stu_obj)
print(name_List) # stu_obj 通过my_study_record 反查 多条上课数据,学生和上课数据是一对多的关系。
# 注意返回值是反查出的student_record对象的返回值
session.commit()

(3)多外键写法:
应用场景:一个表中 两个字段的值 都在 另一个表一个字段里
比如快递要发账单,快递发到收快递人的地址,账单发到付款人的地址,都用的是一个地址表

建表

'''多外键关联'''
from sqlalchemy import create_engine, Integer, ForeignKey, String, Column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

engine =create_engine("mysql+pymysql://root:960314@localhost/pytest",
                      encoding='utf-8',echo=True)


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
Base.metadata.create_all(engine)

API


'''多外键的api'''
from day12 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='Tiantongyuan',city='Changping',state='Bj')
# addr2=orm_many_fk.Address(street='Wudaokou',city='Haidian',state='Bj')
# addr3=orm_many_fk.Address(street='Yanjiao',city='Langfang',state='HB')
#
# session.add_all([addr1,addr2,addr3])
#
# c1 = orm_many_fk.Customer(name='yang',billing_address=addr1,shipping_address=addr2)
# c2 = orm_many_fk.Customer(name='jack',billing_address=addr2,shipping_address=addr1)
#
#
# session.add_all([c1,c2])


obj=session.query(orm_many_fk.Customer).filter(orm_many_fk.Customer.name=='yang').first()
print(obj.name,obj.billing_address,obj.shipping_address)
# session.commit()

(4)多对多关联的外键

比如 一本书可以有多个作者,一个作者又可以出版多本书
应用于 多对多关系

建表

'''多对多关联'''
'''一本书可以有多个作者,一个作者又可以出版多本书'''

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
from sqlalchemy.orm import sessionmaker

engine =create_engine("mysql+pymysql://root:960314@localhost/pytest",
                      encoding='utf-8',echo=True)



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') # 允许author对象调books
                                                                                    # book对象调authors

    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)

API
这里建用户不管心的中间表使用的是非类的创建
删除数据时 orm会自动删除,不用管中间表


'''多对多关联api'''
from day12 import orm_m2m
from sqlalchemy.orm import sessionmaker


Session_class=sessionmaker(bind=orm_m2m.engine)
session=Session_class()

# b1=orm_m2m.Book(name="learn python",pub_date="2018-01-10")
# b2=orm_m2m.Book(name="learn linux",pub_date="2018-02-10")
# b3=orm_m2m.Book(name="learn java",pub_date="2018-03-10")
# session.add_all([b1,b2,b3])
# a1=orm_m2m.Author(name="yang")
# a2=orm_m2m.Author(name="zhangsan")
# a3=orm_m2m.Author(name="lisi")
#
# b1.authors=[a1,a3]
# b3.authors=[a1,a2,a3]
# session.add_all([a1,a2,a3])

# 注意如果 session.add_all([b1,b2,b3,a1,a2,a3]) b3有可能比b2先创建 就会打乱b3和b2的顺序

author_obj=session.query(orm_m2m.Author).filter(orm_m2m.Author.name=="yang").first()
print(author_obj.books) # 返回的是一个对象的列表
print(author_obj.books[1].pub_date)

# book_obj=session.query(orm_m2m.Book).filter(orm_m2m.Book.id==6).first()
# print(book_obj.authors)
session.commit()


# 删除数据时 orm会自动删除,不用管中间表

# 要想写中文 在 engine =create_engine("mysql+pymysql://root:960314@localhost/pytest",encoding='utf-8',echo=True) 写了encoding还不管用
# 必须要写成“mysql+pymysql://root:960314@localhost/pytest?charset=utf8”
# 以后就直接写“mysql+pymysql://root:960314@localhost/pytest?charset=utf8” 不用写encoding了

作业:
基于sqlalchemy ORM框架的学生老师简版管理系统

需求:

用户角色,讲师\学员, 用户登陆后根据角色不同,能做的事情不同,分别如下
讲师视图
  管理班级,可创建班级,根据学员qq号把学员加入班级
  可创建指定班级的上课纪录,注意一节上课纪录对应多条学员的上课纪录, 即每节课都有整班学员上, 为了纪录每位学员的学习成绩,需在创建每节上课纪录是,同时 为这个班的每位学员创建一条上课纪录
  为学员批改成绩, 一条一条的手动修改成绩
学员视图
提交作业
查看作业成绩
一个学员可以同时属于多个班级,就像报了Linux的同时也可以报名Python一样, 所以提交作业时需先选择班级,再选择具体上课的节数
附加:学员可以查看自己的班级成绩排名

github:https://github.com/yyyhhhrrr/student_manage

猜你喜欢

转载自blog.csdn.net/qq_33060225/article/details/84841702