以下所有代碼片段都使用了統一的引用,該引用如下:
from sqlalchemy import create_engine, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, String, Integer, Table from sqlalchemy.orm import relationship, sessionmaker
一、表結構設計
engine = create_engine("mysql+pymysql://root:root@localhost/study?charset=utf8", echo=True) # 連接數據庫,顯示SQL語句 Base = declarative_base() # 創建基類 class Student(Base): __tablename__ = 'students' # 指定表名 __table_args__ = { # "mysql_engine":"MyISAM", "mysql_charset":"utf8" } # show create table students 可以查看建表語句;默認是Innodb,lating-1.如果想顯示中文需要修改指定建表的類型,同時,engine也要指定編碼格式 id = Column(Integer, primary_key=True) #指定主鍵 name = Column(String(30)) #多個字段名 gender = Column(Integer) std_id = Column(String(10)) teacher = Column(String(30)) def __str__(self): #顯示對象的時候打印名字 return self.name Base.metadata.create_all(engine) # 創建所有繼承自 Base 的類對應的表
sqlslchemy在數據庫中創建表之前,會先檢查該表是否存在,如果不存在,才會去創建新表。
class Student(Base): __tablename__ = 'students' # 指定表名 id = Column(Integer, primary_key=True) name = Column(String(30)) gender = Column(Integer) std_id = Column(String(10)) teacher = Column(String(30)) **math = Column(Integer)** #變量字段 def __str__(self): return self.name
雖然新加了一個math
變量(字段),但是由於數據庫中已有students
表,所以不會去創建新表,match
字段也就不存在。
二、基本增刪改查
1.插入數據
Session = sessionmaker(bind=engine) # 獲取 Session類 ses = Session() # 獲取session對象 zhangsan = Student(name="zhangsan", gender=1, std_id='XS331', teacher='hanmeimei', math=90) lisi = Student(name="lisi", gender=1, std_id='XS332', teacher='hanmeimei', math=10) wangwu = Student(name="wangwu", gender=0, std_id='XS333', teacher='lilei', math=60) zhaoliu = Student(name="zhaoliu", gender=0, std_id='XS337', teacher='lilei', math=80) ses.add(zhangsan) # 單條添加 ses.add_all([lisi, wangwu, zhaoliu]) # 批量添加 ses.commit()
2.修改數據
zhangsan = ses.query(Student).filter_by(name='zhangsan').first() #先獲取對象 zhangsan.math = 91 #更改對象的屬性 ses.commit() #提交
也可以在還創建數據的時候修改,就是在提交之前進行修改:
liqi = Student(name="liqi", gender=1, std_id='XS335', teacher='xiadonghai', math=100) #實例化一個對象 ses.add(liqi) #添加對象,也可以視作添加一條數據 liqi = ses.query(Student).filter_by(name='liqi').first() liqi.gender = 0 ses.commit()
在創建一個對象之后,未添加之前直接改變其屬性。
liqi = Student(name="liqi", gender=1, std_id='XS335', teacher='xiadonghai', math=100) liqi.gender = 0 ses.add(liqi) ses.commit()
除此之外還可以使用update。
sess.query(Student).filter_by(name='liming').update({'gender':0}) sess.commit()
3.刪除
result = sess.query(Student).filter(Student.id == 1 ).delete() sess.commit() result = sess.query(Student).filter(Student.id == 2 ).first() sess.delete(result) sess.commit()
4.查詢
查詢操作在數據庫操作中總是最復雜的,下面介紹一些常用的操作。
(1)算術操作符
= 操作符 students_99 = sess.query(Student).filter_by(name ='zhangsan').all() students_100 = sess.query(Student).filter(Student.name == 'zhangsan').all() for i in students_100: print(i.name)
!= 操作符 student_101 = sess.query(Student).filter_by(name != 'liming').all() # error student_98 = sess.query(Student).filter(Student.name != 'liming').all() for i in student_98: print(i.name)
> ,<, <=, >=, 操作符 student_60 = sess.query(Student).filter(Student.math > 10).all() student_61= sess.query(Student).filter_by(math>10).all() # error student_62 = sess.query(Student).filter(Student.math < 100).all() student_63 = sess.query(Student).filter(Student.math <= 90).all() student_64 = sess.query(Student).filter(Student.math >= 90).all() student_64 = sess.query(Student).filter(Student.math <> 90).all() # error for i in student_60: print(i.math) for i in student_62: print(i.math) for i in student_63: print(i.math) for i in student_64: print(i.math)
(2)模糊查詢
like 操作符 % 代表任意多個字符 _ 代表一個字符 student_17 = sess.query(Student).filter(Student.name.like("%i%")).all() for i in student_17: print(i.name) student_17_2 = sess.query(Student).filter(Student.name.like("%i_i")).all() for i in student_17_2: print(i.name) not like student_70 = sess.query(Student).filter(~Student.name.like("%i_i")).all() student_71 = sess.query(Student).filter(Student.name.notlike("%i_i")).all() for i in student_70: print(i.name) print(student_70 == student_71)
(3)區間選取
in 操作符 student_18 = sess.query(Student).filter(Student.name.in_(['zhangsan','lisi','wangwu'])).all() for i in student_18: print(i.name) not in student_19 = sess.query(Student).filter(~Student.name.in_(['lisi'])).all() student_19_2 = sess.query(Student).filter(Student.name.notin_(['lisi'])).all() for i in student_19: print(i.name) print(student_19 == student_19_2)
(4)分頁
student_10 = sess.query(Student).limit(2).offset(1).all() #從第幾條開始選取幾條 student_11 = sess.query(Student).offset(1).limit(2).all() student_12 = sess.query(Student)[1:3] for i in student_10: print(i.id) for i in student_11: print(i.id) for i in student_12: print(i.id)
(5)排序
order_by 排序 student_33 = sess.query(Student).filter(text("math >= 10")).order_by(~text("math")).all() # 逆序 student_33_2 = sess.query(Student).filter(text("math >= 10")).order_by(text("math")).all() # 順序 student_33_2_1 = sess.query(Student).filter(text("math >= 10")).order_by(desc(text("math"))).all() # 逆序 student_33_3 = sess.query(Student).order_by(desc(Student.math)).all() # 逆序 student_33_4 = sess.query(Student).order_by(Student.math.desc()).all() # 逆序 student_33_5 = sess.query(Student).order_by(~Student.math).all() # 逆序 student_33_6 = sess.query(Student).order_by(Student.math).all() # 順序 print(student_31) print(student_32) print("___"* 30) for i in student_33: print(i.math) print("___"* 30) for i in student_33_2: print(i.math) for i in student_33_3: print(i.math) for i in student_33_4: print(i.math) for i in student_33_5: print(i.math) for i in student_33_6: print(i.math)
(6)分組
group_by 分組 student_39 = sess.query(Student).group_by(Student.gender == 1).count() print(student_39)
(7)having:分組之后條件過濾
having student_39_1 = sess.query(Student).group_by(Student.gender == 1).having(Student.math>60).all() for i in student_39_1: print(i)
(8)計數
count student_38 = sess.query(Student).filter_by(gender=1).count() student_38_2 = sess.query(func.count(Student.name),Student.name).group_by(Student.name).all() student_38_3 = sess.query(func.count(Student.name),Student.gender).group_by(Student.gender).all() print(student_38_2) print(student_38_3)
(9)去重
distinct student_40 = sess.query(distinct(Student.name)).all() for i in student_40: print(i)
(10)空值
是否為null student_20 = sess.query(Student).filter(Student.name != None).all() student_21 = sess.query(Student).filter(~Student.name.is_(None)).all() student_22 = sess.query(Student).filter(Student.name.isnot(None)).all() student_21_3 = sess.query(Student).filter(Student.name.is_('zhangsan')).all() # error student_21_2 = sess.query(Student).filter(Student.name.is_(1)).all() for i in student_20: print(i.name) print(student_20 == student_21 == student_22) student_23 = sess.query(Student).filter(Student.math.is_(90)).all() student_24 = sess.query(Student).filter(Student.math == None).all()
(11)邏輯操作
and student_25 = sess.query(Student).filter(Student.gender == 1, Student.math > 70).all() student_26 = sess.query(Student).filter(and_(Student.gender == 1, Student.math > 70)).all() # 別忘了引入該方法 student_27 = sess.query(Student).filter(Student.gender == 1).filter(Student.math > 70).all() for i in student_25: print(i.name) print(student_25 == student_26 == student_27) or student_28 = sess.query(Student).filter(or_(Student.gender == 1, Student.math > 80)).all() for i in student_28: print(i.name)
(12)text:原生sql語句
text 原生sql條件語句 student_31 = sess.query(Student).filter(text("name='lisi'")).first() # 注意值為字符串時的寫法 student_32 = sess.query(Student).filter(text("id=1")).first() # 注意值為 數字 的寫法 student_31 = sess.query(Student).filter(text("id>1 and math>10")).all() for i in student_31: print(i.name) text 插入變量 student_34 =sess.query(Student).filter(text("gender=:sex and math>:score")).params(sex=1, score=1).all() for i in student_34: print(i.name) from_statement 原生sql語句 student_35 = sess.query(Student).from_statement(text("select * from students where id=:id")).params(id=1).one() student_36 = sess.query(Student).from_statement("select * from students where math>:score").params(score=10).all() student_36_1 = sess.query(Student).from_statement("select * from students where math>10").all() print(student_35) for i in student_36: print(i.name) print(student_36 == student_36_1)
(13)使用別名
student_7 = sess.query(Student.name.label('std_name')).all() print(student_7) for i in student_7: print(i.std_name) print(i[0]) # 第二種取值方式 student_8 = sess.query(Student.name).all() print(student_8) for i in student_8: print(i.name) print(i[0])
(14)取值
根據主鍵獲取對象 students_1 = sess.query(Student).get(1) print(students_1 value指定要獲取的字段 返回的是生成器 students_3 = sess.query(Student).value(Student.name) print(students_3) values 指定多個字段 返回的是生成器 students_3_2 = sess.query(Student).values(Student.id,Student.name) print(students_3_2) for i in students_3_2: print(i) 一次獲取多個字段值 students_4 = sess.query(Student.name,Student.gender).all() print(students_4) for i in students_4: print(i) 后續添加的方式選擇要得到的字段結果 students_5 = sess.query(Student.name).add_columns(Student.gender).all() print(students_5) student_6 = sess.query(Student).filter_by(name="王大麻子").one() print(student_6) 錯誤用法 error_1 = sess.query(Student).filter_by(and_(Student.id == 1, Student.name == 'lisi')).first() error_2 = sess.query(Student).filter_by(and_(id=1, name='lisi')).first() error_3 = sess.query(Student).filter(and_(id=1, name='lisi')).first() one 有且只有一個,否則報錯 student_30 = sess.query(Student).filter(Student.id == 1).one() print(student_30) 可以只有一個或者沒有,不能為多個結果,否則報錯 student_31 = sess.query(Student).filter(Student.id == 10).one_or_none() print(student_31) student_13 = sess.query(Student).filter_by(id=1).one_or_none() student_14 = sess.query(Student).filter(Student.id == 1).one_or_none() print(student_13) print(student_14)
(15)chain鏈式調用
student_15 = sess.query(Student).filter_by(gender=1).filter(Student.math>80).all() # student_15_2 = sess.query(Student).filter_by(gender=1).filter_by(math>80).all() # error student_16 = sess.query(Student).filter(Student.gender == 1).filter(Student.math>80).all() for i in student_15: print(i.name) for i in student_16: print(i.name)