1. 程式人生 > >老男孩14期自動化運維day12隨筆和作業

老男孩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:[email protected]/pytest”,encoding=‘utf-8’,echo=True) 寫了encoding還不管用
必須要寫成“mysql+pymysql://root:[email protected]/pytest?charset=utf8”
以後就直接寫“mysql+pymysql://root:[email protected]/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:[email protected]/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:[email protected]/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:[email protected]/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:[email protected]/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:[email protected]/pytest",encoding='utf-8',echo=True) 寫了encoding還不管用
# 必須要寫成“mysql+pymysql://root:[email protected]/pytest?charset=utf8”
# 以後就直接寫“mysql+pymysql://root:[email protected]/pytest?charset=utf8” 不用寫encoding了

作業:
基於sqlalchemy ORM框架的學生老師簡版管理系統

需求:

使用者角色,講師\學員, 使用者登陸後根據角色不同,能做的事情不同,分別如下
講師檢視
  管理班級,可建立班級,根據學員qq號把學員加入班級
  可建立指定班級的上課紀錄,注意一節上課紀錄對應多條學員的上課紀錄, 即每節課都有整班學員上, 為了紀錄每位學員的學習成績,需在建立每節上課紀錄是,同時 為這個班的每位學員建立一條上課紀錄
  為學員批改成績, 一條一條的手動修改成績
學員檢視
提交作業
檢視作業成績
一個學員可以同時屬於多個班級,就像報了Linux的同時也可以報名Python一樣, 所以提交作業時需先選擇班級,再選擇具體上課的節數
附加:學員可以檢視自己的班級成績排名

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