sqlalchemy查詢使用

sqlalchemy查詢使用

 1.帶條件查詢

查詢是最常用的,對於各種查詢我們必須要十分清楚,首先是帶條件的查詢


 
  1. #帶條件查詢

  2. rows = session.query(User).filter_by(username='jingqi').all()

  3. print(rows)

  4. rows1 = session.query(User).filter(User.username=='jingqi').all()

  5. print(rows1)

  6. rows2 = session.query(User.username).filter(User.username=='jingqi').all()

  7. print(rows2)

  8. rows3 = session.query(User.username).filter(User.username=='jingqi')

  9. print(rows3)

`filter_by`和`filter`都是過濾條件,只是用法有區別`filter_by`裏面不能用`!= `還有`> <` 等等,所有`filter`用得更多,`filter_by`只能用`=`。

前兩個查詢的是`User`,所以返回結果也是一個對象,但是`rows2`查詢的是屬性值,所以返回的是屬性值。

`rows3`可以看到`SQLAlchemy `轉成的`SQL`語句,`SQLAlchemy`最後都是會轉成`SQL`語句,通過這個方法可以查看原生`SQL`,甚至有些時候我們需要把`SQLAlchemy`轉成的`SQL`交給DBA審查,合適的才能使用。

查詢要知道查詢結果的返回怎樣的數據


 
  1. print( session.query(User).filter(User.username=='jingqi').all() )

  2. print( session.query(User).filter(User.username=='jingqi').first())

  3. print( session.query(User).filter(User.username=='jingqi').one())#結果爲一個時正常,多了就報錯

  4. print( session.query(User).get(2))#通過id查詢

上面三條記錄,第一個查出所有符合條件的記錄,第二個查出所有符合記錄的第一條記錄,第三個返回一個對象,如果結果有多條就會報錯,第四個通過主鍵獲取記錄

除此之外,我們偶爾也會需要限制返回的結果數量


 
  1. #限制查詢返回結果

  2. print( session.query(User).filter(User.username!='jingqi').limit(2).all())

  3. print( session.query(User).filter(User.username!='jingqi').offset(2).all())

  4. print( session.query(User).filter(User.username!='jingqi').slice(2,3).all())

 #可以排序之後再進行限制
 from sqlalchemy import desc
 print( session.query(User).filter(User.username!='budong').order_by(User.username).all())
 print( session.query(User).filter(User.username!='budong').order_by(desc(User.username)).slice(1,3).all())

第一個是限制返回條數,從第一條開始;第二個是從第三條開始返回查詢結果;第三個是切片返回記錄。

`order_by`默認是順序,`desc`是降序。

還有其他的帶條件查詢


 
  1. #不等於

  2. print( session.query(User).filter(User.username!='jingqi').all() )

  3. #模糊匹配 like

  4. print( session.query(User).filter(User.username.like('jingqi')).all() )

  5. print( session.query(User).filter(User.username.notlike('jingqi')).all() )

  6. #成員屬於 in_

  7. print( session.query(User).filter(User.username.in_(['jingqi','jingqi1'])).all() )

  8. #成員不屬於 notin_

  9. print( session.query(User).filter(User.username.notin_(['jingqi','jingqi2'])).all() )

  10. #空判斷

  11. print( session.query(User).filter(User.username==None).all() )

  12. print( session.query(User).filter(User.username.is_(None)).all() )

  13. print( session.query(User).filter(User.username.isnot(None)).all() )

  14. #多條件

  15. print( session.query(User).filter(User.username.isnot(None),User.password=='qwe123').all() )

  16. #選擇條件

  17. from sqlalchemy import or_,and_,all_,any_

  18. print( session.query(User).filter(or_(User.username=='jingqi',User.password=='qwe123')).all() )

  19. print( session.query(User).filter(and_(User.username=='jingqi2',User.password=='111')).all() )

以上是各種帶條件的查詢,大家知道怎麼使用,但是需要注意的是,所以的模糊匹配是十分耗費時間的,能不用就儘量不要用。

當然還有聚合函數的使用


 
  1. from sqlalchemy import func,extract

  2. print( session.query(User.password,func.count(User.id)).group_by(User.password).all() )

  3. print( session.query(User.password,func.count(User.id)).group_by(User.password).having(func.count(User.id)>1).all() )

  4. print( session.query(User.password,func.sum(User.id)).group_by(User.password).all() )

  5. print( session.query(User.password,func.max(User.id)).group_by(User.password).all() )

  6. print( session.query(User.password,func.min(User.id)).group_by(User.password).all() )

  7. #使用extract提取時間中的分鐘或者天來分組

  8. print( session.query(extract('minute', User.creatime).label('minute'),func.count('*').label('count')).group_by('minute').all() )

  9. print( session.query(extract('day', User.creatime).label('day'),func.count('*').label('count')).group_by('day').all() )

這裏只是告訴大家的用法,其中`group_by`是分組,如果要使用聚合函數,就必須導入`func`,`label`是取別名的意思 。

2.表關係查詢

對於有表關係的,也有些不同的查詢,首先我們來建立一個有外鍵關係的表


 
  1. from sqlalchemy.orm import relationship

  2. from sqlalchemy import ForeignKey

  3.  
  4. class UserDetails(Base):

  5. __tablename__ = 'user_details'

  6. id = Column(Integer,primary_key=True,autoincrement=True)

  7. id_card = Column(Integer,nullable=False,unique=True)

  8. lost_login = Column(DateTime)

  9. login_num = Column(Integer,default=0)

  10. user_id = Column(Integer,ForeignKey('user.id'))

  11.  
  12. userdetail_for_foreignkey = relationship('User',backref='details',uselist=False,cascade='all')

  13.  
  14. def __repr__(self):

  15. return '<UserDetails(id=%s,id_card=%s,lost_login=%s,login_num=%s,user_id=%s)>'%(

  16. self.id,

  17. self.id_card,

  18. self.login_login,

  19. self.login_num,

  20. self.user_id

  21. )

這裏要注意`relationship`默認是一對多的關係,使用`uselist=False`則表示一對一的關係,`cascade` 是自動關係處理,就和MySQL中的`ON DELETE`類似,但是有區別,參數選項如下:

`cascade` 所有的可選字符串項是:

- *all* , 所有操作都會自動處理到關聯對象上.
- *save-update* , 關聯對象自動添加到會話.
- *delete* , 關聯對象自動從會話中刪除.
- *delete-orphan* , 屬性中去掉關聯對象, 則會話中會自動刪除關聯對象.
- *merge* , `session.merge()` 時會處理關聯對象.
- *refresh-expire* , `session.expire()` 時會處理關聯對象.
- *expunge* , `session.expunge()` 時會處理關聯對象.

有如上的表關係之後,查詢可以十分方便


 
  1. #表關係查詢

  2. row = session.query(UserDetails).all()

  3. print(row,dir(row[0]))

  4. row = session.query(User).filter(User.id==1).first()

  5. print(row,dir(row))

  6. print(row.details)

  7. print(row.details[0].lost_login)

`relationship`會在`User`表裏面添加一個屬性,通過這個屬性就可以查詢對應的`user_details`表中的所有字段。省去了很多的代碼。

3.多表查詢

多表查詢也是必須要掌握的知識點。以下是常見的幾種表關聯方式,需要熟練掌握。


 
  1. #多表查詢

  2. print( session.query(UserDetails,User).all() ) #這個是 cross join

  3. print( session.query(UserDetails,User).filter(User.id==UserDetails.id).all() ) #這是也是cross join 但是加上了where條件

  4.  
  5. print( session.query(User.username,UserDetails.lost_login).join(UserDetails,UserDetails.id==User.id).all() ) #這個是inner join

  6.  
  7. print( session.query(User.username,UserDetails.lost_login).outerjoin(UserDetails,UserDetails.id==User.id).all() ) #這個纔是左連接,sqlalchemy沒有右連接

  8.  
  9. q1 = session.query(User.id)

  10. q2 = session.query(UserDetails.id)

  11. print(q1.union(q2).all()) #這個是union關聯

除了上面的幾種關聯方式,子表查詢也是用得很多的,也是要掌握的


 
  1. from sqlalchemy import all_,any_

  2. sql_0 = session.query(UserDetails.lost_login).subquery() #這是聲明一個子表

  3. print( session.query(User).filter((User.creatime > all_(sql_0)) ).all() )

  4. print( session.query(User).filter((User.creatime > any_(sql_0)) ).all() )

注意`any_`和`all_`的區別,`all_`要求的是所有都滿足,`any_`只需要有滿足的就行。

4.原生SQL的查詢以及其他使用

再次強調,使用`ORM`或者原生`SQL`沒有絕對的那個好一點,怎麼方便怎麼使用。


 
  1. #第一步寫好原生的sql,如果需要傳遞參數,可以使用字符串拼接的方式

  2. sql_1 = """

  3. select * from `user`

  4. """

  5. #第二步執行,得到返回的結果

  6. row = session.execute(sql_1)

  7. print(row,dir(row))

  8. #第三步,自己控制得到數據的方式

  9. print( row.fetchone() )

  10. print( row.fetchmany() )

  11. print( row.fetchall() )

  12. #也可以循環獲得

  13. for i in row:

  14. print('===',i)

轉載:https://www.cnblogs.com/jingqi/p/8059673.html

 tornado客戶端使用sqlalchemy遇到的問題:

1、tornado客戶端需要的cookie
#來源
print response.headers.get_all
cookies = response.headers.get_list("Set-Cookie")
cookies = dict([l.split("=", 1) for l in cookies[0].split(";")])
print cookies["_xsrf"]
#設置
h = tornado.httputil.HTTPHeaders()#{"content-type": "text/html"}
h.add("X-Xsrftoken",cookies["_xsrf"])
h.add("Cookie","_xsrf="+cookies["_xsrf"])

2、server獲取請求參數不到

h = tornado.httputil.HTTPHeaders({"content-type": "text/html"})
設置之後,參數在body裏面,而不是在body_arguments或qurey_arguments

js側,data: {"data":JSON.stringify(res)},

可以直接處理self.request.body,如果是json格式的body,也這樣解析json.loads(self.request.body)

3、sqlalchemy查詢語句
session.query(User|User.name, User.id).jion(UserDetail, UserDetail.id=User.id).filter(User.name=='wangmei',A.id=B.id).(order_by(desc(User.username))).(limit(2), offset(2), slice(2,4)).(all()|first()|one())                        #儘量不要cross jion即沒有join,outerjoin

4、異常的時候要回滾

try:
    obj = Network(type=ntype, start_ip=start_ip, end_ip=end_ip, mask=get_mask(int(mask_len)), gateway_ip=gateway_ip)
    session.add(obj)
    session.commit()
    # 返回表id
    self.write(str(obj.nid))
except Exception as e:
    session.rollback()
    print e

5、sqlalchemy的修改和刪除

先查找到相應記錄result

result.name =newname

result.delete(result)

session.commit()

6、sqlalchemy級聯刪除一對多


 
  1. ips = relationship("Ip", cascade='delete')

  2. sid = Column(Integer, ForeignKey('server.sid', ondelete='CASCADE'))

  3. https://docs.sqlalchemy.org/en/rel_0_9/orm/cascades.html#delete

級聯刪除的實質是,先刪除相應的子節點再刪除父節點。

當父節點刪除時候,子節點有幾個選擇:禁止父刪除,將父節點改爲null,保持不變,都可以設置;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章