上節(jié)課使用query從數(shù)據(jù)庫中查詢到了結(jié)果,但是query返回的對象是直接可用的嗎?
query:
from connect import session
from user_module import User
result = session.query(User)
print(result,type(result)) #返回是一個(gè)query對象,打印出來可以看到轉(zhuǎn)化過后的SQL
根據(jù)以上返回是一個(gè)query對象施流,打印出來可以看到轉(zhuǎn)化過后的SQL。
filter:
from connect import session
from user_module import User
result = session.query(User).filter(User.username=='cainiao')
print(result,type(result)) #返回是一個(gè)query對象鄙信,打印出來可以看到轉(zhuǎn)化過后的SQL
根據(jù)以上返回是一個(gè)query對象瞪醋,打印出來可以看到轉(zhuǎn)化過后的SQL。
all:
all 是返回所有符合條件的數(shù)據(jù)装诡。
result = session.query(User).filter(User.username=='cainiao').all()
print(result,type(result)) ##返回的是一個(gè)list,列表里面是一個(gè)類
根據(jù)以上返回的是一個(gè)list,列表里面是一個(gè)類银受。
first:
first 是返回所有符合條件數(shù)據(jù)的第一條數(shù)據(jù)践盼。
result = session.query(User).filter(User.username=='cainiao').first()
print(result,type(result)) #返回類的實(shí)例化
根據(jù)以上返回的是類的實(shí)例化
索引
result1 = session.query(User)
print(result1,type(result1)) #返回是一個(gè)query對象,打印出來可以看到轉(zhuǎn)化過后的SQL
result2 = session.query(User)[0]
print(result2,type(result2)) #返回類的實(shí)例化
result3 = session.query(User).all()[0]
print(result3,type(result3)) #返回類的實(shí)例化
result4= session.query(User).first()
print(result4,type(result4)) #返回類的實(shí)例化
索引為0的值蚓土,類似于first宏侍,但是不等同于,空列表用這個(gè)會報(bào)錯(cuò)J衿帷谅河!
取值
對于類的實(shí)例化可以用.
和getattr
來獲取字段值
#對于類的實(shí)例化可以用.來獲取字段值
print(result2.username)
print(result3.username)
print(result4.username)
#也可以用getattr方法
print(getattr(result2,'username'))
print(getattr(result2,'username'))
print(getattr(result2,'username'))
在query里面指定了某個(gè)屬性值,返回是直接查詢User.username的值确丢,所以就返回了包括元組的列表
result = session.query(User.username).all()
print(result,type(result)) #在query里面指定了某個(gè)屬性值绷耍,返回是直接查詢User.username的值,所以就返回了包括元組的列表
print(session.query(User.username).first()) #返回元祖
過濾函數(shù)
filter是一個(gè)過濾函數(shù)鲜侥,過濾條件都可以書寫在次函數(shù)中褂始,不同的條件之間用逗號隔開。filter_by 也是一個(gè)過濾函數(shù)描函,但是功能要弱一些崎苗。
result1 = session.query(User).filter(User.username=='cainiao',User.password=='1').all()
print(result1)
result2 = session.query(User).filter_by(username='cainiao').all()
print(result2)
區(qū)別:
二者都是 過濾函數(shù),但是使用有如下差別:
- filter 中需要添加 類對象舀寓,filter_by不需要胆数。
- filter_by 中只能添加等于的條件,不能添加 不等于互墓、大于小于等條件必尼,filter沒有這個(gè)限制。
模糊查詢
like和notlike
like 是模糊查詢篡撵,和數(shù)據(jù)庫中的 like 用法一樣判莉,notlike 和 like 作用相反。
#like 是模糊查詢育谬,和數(shù)據(jù)庫中的 like 用法一樣券盅,notlike 和 like 作用相反。
result1 = session.query(User.id).filter(User.username.like('cainiao%')).all()
result2 = session.query(User.id).filter(User.username.notlike('cainiao%')).all()
print(result1,result2)
in_和notin_
in_ 和 notin_ 是范圍查找
result1 = session.query(User.id).filter(User.username.in_(['cainiao', 'cainiao1'])).all()
result2 = session.query(User.id).filter(User.username.notin_(['cainiao2', 'cainiao3'])).all()
print(result1,result2)
is_和isnot
is_ 和 isnot精確查找
#is_ 和 isnot精確查找
result1 = session.query(User.id).filter(User.username.is_(None)).all()
result2 = session.query(User.id).filter(User.username.isnot(None)).all()
print(result1,result2)
#判斷為空還可以使用:
result3 = session.query(User.id).filter(User.username==None).all()
print(result3)
查詢結(jié)果
#先用 all 查看所有的數(shù)據(jù)
result1 = session.query(User.username).filter(User.username!='cainiao%').all()
#查看前2條數(shù)據(jù)
result2 = session.query(User.username).filter(User.username!='cainiao').limit(2).all()
#偏移一條記錄膛檀,偏移1個(gè)锰镀,前面1個(gè)數(shù)據(jù)不看,從第2個(gè)數(shù)據(jù)開始查詢
result3 = session.query(User.username).filter(User.username!='cainiao').offset(1).all()
#slice 對查詢出來的數(shù)據(jù)進(jìn)行切片取值,#切片宿刮,索引0到1的數(shù)據(jù)
result4 = session.query(User.username).filter(User.username!='cainiao').slice(0,2).all()
#one 查詢一條數(shù)據(jù)互站,如果存在多條則報(bào)錯(cuò),可以用來測試是否只有一條
result5 = session.query(User.username).filter(User.username!='cainiao').one()
排序
#導(dǎo)入模塊
from sqlalchemy import desc,asc
#默認(rèn)正序私蕾,asc也是正序
result1 = session.query(User.id).filter(User.username=='cainiao').order_by(User.id).all()
result2 = session.query(User.id).filter(User.username=='cainiao').order_by(asc(User.id)).all()
#desc 是倒序排序
result3 = session.query(User.id).filter(User.username=='cainiao').order_by(desc(User.id)).all()
#order_by 和 limit 一起使用的時(shí)候
result4 = session.query(User.id).filter(User.username=='cainiao').order_by(User.id).limit(2).all()
print(result1,type(result1))
print(result2,type(result2))
print(result3,type(result3))
print(result4,type(result4))
默認(rèn)為正序僵缺,asc。desc為倒序踩叭。
函數(shù)
#導(dǎo)入
from sqlalchemy import func,extract
result1 = session.query(func.count(User.id)).all() #select count(id) from users
#用到group_by 磕潮,查詢的列是分組的列翠胰,或者某個(gè)列的聚合函數(shù)
result2 = session.query(User.username).group_by(User.username).all() #select username from users group by username
result3 = session.query(User.username,func.count(User.id)).group_by(User.username).all() #select username,count(id) from users group by username
result4 = session.query(User.username).group_by(User.username).having(func.count(User.id)<4).all()
#group_by 和 order_by 一樣,是可以直接使用的自脯,不需要導(dǎo)入,having 也可以直接使用之景,使用方法也和 SQL 中使用類似。
print(result1,type(result1))
print(result2,type(result2))
print(result3,type(result3))
print(result4,type(result4))
用到group_by 膏潮,查詢的列是分組的列锻狗,或者某個(gè)列的聚合函數(shù)。
聚合函數(shù)
#sum 求和
result1 = session.query(func.sum(User.id)).filter(User.username=='cainiao').all()
#max 求最大值
result2 = session.query(func.max(User.id)).filter(User.username=='cainiao').all()
#min 求最小值
result3 = session.query(func.min(User.id)).filter(User.username=='cainiao').all()
print(result1)
print(result2)
print(result3)
常用聚合函數(shù):count 焕参、 sum avg 轻纪、 max 、 min
extract
#extract 提取對象中的數(shù)據(jù)叠纷,這里提取分鐘刻帚,并把提取出來的結(jié)果用 label 命名別名,之后就可以使用 group_by 來分組
session.query(extract('minute',User.creatime).label('minute'), func.count(User.id)).group_by('minute').all()
選擇條件
from sqlalchemy import or_
result1 = session.query(User.id).filter(User.username=='cainiao').all()
result2 = session.query(User.id).filter(User.id==3).all()
result3 = session.query(User.id).filter(or_(User.username=='cainiao',User.id==3)).all()
print(result1)
print(result2)
print(result3)
多表查詢
新建module
class UserDetails(Base):
__tablename__ = 'user_details'
id = Column(Integer,primary_key=True,autoincrement=True)
id_card = Column(Integer,nullable=True,unique=True)
last_login =Column(DateTime)
login_num = Column(Integer,default=0)
user_id = Column(Integer,ForeignKey('users.id'))
def __repr__(self):
return '<UserDetails(id=%s,id_card=%s,' \
'last_login=%s,login_num=%s,user_id=%s)>'%(self.id,self.id_card,self.last_login,self.login_num,
self.user_id)
cross join笛卡爾積
cross join交叉連接涩嚣。交叉連接返回左表中的所有行崇众,左表中的每一行與右表中的所有行組合。交叉連接也稱作笛卡爾積航厚。
from user_module import UserDetails
result1 = session.query(UserDetails,User) #cross join 第一張表每一項(xiàng)與第二張表交叉連接
print(result1,type(result1))
inner join內(nèi)連接
內(nèi)連接inner join顷歌,內(nèi)連接,只查匹配行阶淘。
result2 = session.query(User.username, UserDetails.last_login).join(UserDetails,UserDetails.id==User.id) #內(nèi)連接
print(result2)
外連接
外連接衙吩,至少有一方保留全集,沒有匹配行用NULL代替溪窒。外連接分為三種:左外連接坤塞,右外連接,全外連接澈蚌。對應(yīng)SQL:LEFT/RIGHT/FULL OUTER JOIN摹芙。通常我們省略outer 這個(gè)關(guān)鍵字。寫成:LEFT/RIGHT/FULL JOIN宛瞄。
- 左外連接:左表不加限制浮禾,保留左表的數(shù)據(jù),匹配右表份汗,右表沒有匹配2到的行中的列顯示為null盈电。
- 右外連接:右表不加限制,保留右表的數(shù)據(jù)杯活。匹配左表匆帚,左表沒有匹配到的行中列顯示為null。
- 完全外連接:左右表都不加限制旁钧。即右外連接的結(jié)果為:左右表匹配的數(shù)據(jù)+左表沒有匹配到的數(shù)據(jù)+右表沒有匹配到的數(shù)據(jù)吸重。
#左連接 left join結(jié)果集保留左表的所有行互拾,但只包含第二個(gè)表與第一表匹配的行。第二個(gè)表相應(yīng)的空行被放入NULL值嚎幸。
result3 = session.query(User.username, UserDetails.last_login).outerjoin(UserDetails,UserDetails.id==User.id) #左連接
print(result3,type(result3))
#sqlalchemy沒有right join颜矿,右連接將表反過來寫即可。
result4 = session.query(UserDetails.last_login,User.username).outerjoin(User,User.id==UserDetails.id)
print(result4,type(result4))
union
union 是聯(lián)合查詢嫉晶,有自動去重的功能骑疆,對應(yīng)的還有 union_all,UNION 操作符用于合并兩個(gè)或多個(gè) SELECT 語句的結(jié)果集。
#union 是聯(lián)合查詢替废,有自動去重的功能封断,對應(yīng)的還有 union_all,UNION 操作符用于合并兩個(gè)或多個(gè) SELECT 語句的結(jié)果集。
q1 = session.query(User.id)
q2 = session.query(UserDetails.id)
result1 = q1.union(q2)
result2 = q1.union_all(q2)
print(q1.all())
print(q2.all())
print(result1.all(),type(result1))
print(result2.all(),type(result2))
union:聯(lián)合的意思舶担,即把兩次或多次查詢結(jié)果合并起來坡疼。
要求:兩次查詢的列數(shù)必須一致
推薦:列的類型可以不一樣,但推薦查詢的每一列衣陶,想對應(yīng)的類型以一樣
可以來自多張表的數(shù)據(jù):多次sql語句取出的列名可以不一致柄瑰,此時(shí)以第一個(gè)sql語句的列名為準(zhǔn)。
如果不同的語句中取出的行剪况,有完全相同(這里表示的是每個(gè)列的值都相同)教沾,那么union會將相同的行合并,最終只保留一行译断。也可以這樣理解授翻,union會去掉重復(fù)的行。
如果不想去掉重復(fù)的行孙咪,可以使用union all堪唐。
子表查詢
是指出現(xiàn)在其他SQL語句內(nèi)的SELECT字句。嵌套在查詢內(nèi)部翎蹈,且必須始終出現(xiàn)在圓括號內(nèi)淮菠。子查詢里面只能查詢一個(gè)東西,不能查詢多個(gè)荤堪,因?yàn)橥饷娼邮盏闹荒芙邮找粋€(gè)合陵。
#子表查詢
#subquery聲明子表
sql_0 =session.query(UserDetails.last_login).subquery()
#使用
result2 = session.query(User,sql_0.c.last_login)
print(result2)
原生sql查詢
sql = "select * from users"
row = session.execute(sql)
print(row.fetchall()) #注意類似游標(biāo)指針一次查詢指針會指到本次查詢的末尾處
print(row.fetchone())
print(row.fetchmany())
#循環(huán)獲取
for i in row:
print(i)
pycharm快速添加數(shù)據(jù)
點(diǎn)擊右邊Database:
點(diǎn)擊添加:
設(shè)置配置信息:
測試連接成功,點(diǎn)擊保存:
點(diǎn)擊右邊就可以在左邊進(jìn)行相關(guān)操作了