SQLAlchemy是Python編程語言下的一款ORM框架,該框架創建在數據庫API之上,使用關係對象映射進行數據庫操做。將對象轉換成SQL,而後使用數據API執行SQL並獲取執行結果。在寫項目的過程當中,經常要使用SQLAlchemy操做數據庫,同事前期教我不少東西,感謝之餘寫一篇文章記錄使用過的技術,作到內心有數,手上有活。python
在開發過程當中涉及到的內容:mysql
相關查詢操做還有:sql
最後補充:數據庫
1.sqlalchmey開發環境的搭建編程
pip install sqlalchemy
2.安裝mysql數據庫session
sudo apt-get install mysql-server
3.建立數據庫mydb框架
create database mydb default charset utf8
建立數據庫時必定要加上數據的編碼方式,不然沒法存入中文。編程語言
4.下載mysql的python驅動工具
apt install MySQL-python
建立表結構編碼
定義四張表:Student,Family,House,Car。關係以下:
代碼建立過程:
1 from sqlalchemy import Column,String,create_engine,MetaData,ForeignKey,Integer 2 from sqlalchemy.orm import sessionmaker 3 from sqlalchemy.ext.declarative import declarative_base 4 from sqlalchemy.orm import sessionmaker 5 6 Base = declarative_base() 7 meta = MetaData() 8 9 10 #定義User對象 11 class Student(Base): 12 __tablename__ = 'student' 13 id = Column(String(20),primary_key=True) 14 name = Column(String(20)) 15 16 class Family(Base): 17 __tablename__ = 'family' 18 id = Column(String(20),primary_key=True) 19 member = Column(Integer) 20 student_id = Column(String(20),ForeignKey('student.id')) 21 22 class House(Base): 23 __tablename__ = 'house' 24 id = Column(String(20),primary_key=True) 25 location = Column(String(100)) 26 family_id = Column(String(20),ForeignKey('family.id')) 27 28 class Car(Base): 29 __tablename__ = 'car' 30 id = Column(String(20),primary_key=True) 31 name = Column(String(100)) 32 family_id = Column(String(20)) 33 34 35 def create_fun(): 36 37 #初始數據庫鏈接 38 engine = create_engine('mysql+mysqldb://root:123@127.0.0.1:3306/mydb?charset=utf8',echo=True) 39 #建立DBsession 40 DBSession = sessionmaker(bind=engine) 41 42 #建立session會話,數據庫操做的基石。 43 session = DBSession() 44 45 #在數據庫中建立表user 46 Student.metadata.create_all(bind=engine) 47 Family.metadata.create_all(bind=engine) 48 House.metadata.create_all(bind=engine) 49 50 #插入數據 51 stu_one = Student(id='1',name= '悟空') 52 stu_two = Student(id='2',name='貝吉塔') 53 stu_three = Student(id='3',name='比克') 54 stu_four = Student(id='4',name='') 55 56 #提交數據到session 57 58 session.add(stu_one) 59 session.add(stu_two) 60 session.add(stu_three) 61 62 session.add(stu_four) 63 session.commit() 64 65 family_one = Family(id='1',member=7,student_id='1') 66 family_two = Family(id='2',member=5,student_id='2') 67 family_three = Family(id='3',member=8,student_id='3') 68 69 session.add(family_one) 70 session.add(family_two) 71 session.add(family_three) 72 session.commit() 73 74 house_one = House(id='1',location='地球',family_id='1') 75 house_two = House(id='2',location='貝吉塔星',family_id='2') 76 house_three = House(id='3',location='美剋星人',family_id='3') 77 house_four = House(id='4',location='地球',family_id='3') 78 79 session.add(house_one) 80 session.add(house_two) 81 session.add(house_three) 82 session.add(house_four) 83 session.commit() 84 85 car_one = Car(id='1',name='筋斗雲',family_id='1') 86 car_two = Car(id='2',name='奔馳',family_id='2') 87 car_three = Car(id='3',name='寶馬',family_id='3') 88 89 session.add(car_one) 90 session.add(car_two) 91 session.add(car_three) 92 #提交到數據庫 93 session.commit() 94 95 session.close() 96 97 if __name__ == '__main__': 98 create_fun()
建立了四張表,寫入了多條數據。
首先來一波基礎查詢,瞭解各個表的數據。
student表
Family表
House表
Car表
兩張表連表查詢
查詢Student表,限制條件是Family表中的member字段。Family表外鍵關聯到Student表,查詢Family中member 大於6的Student表數據。即家庭成員大於6人的學生表。
result = session.query(Student).join(Family).filter(Family.member>6)
兩張表連表查詢使用了join關鍵字。 將Family表添加到Student表中,經過外鍵關聯到一塊兒。經過打印的查詢sql語句能夠看出,sqlalchemy的join使用的是'INNER JOIN',即內鏈接方式。能夠說,內鏈接方式是sqlalchemy的默認鏈接方式。
三張表連表查詢
查詢Student表,限制的條件是House表中的location字段。
result_two = session.query(Student).join(Family).join(House).filter(House.location=='美剋星人')
查詢語句使用了兩次join,student錶鏈接了family和house。底層的sql查詢語句一樣使用了INNER JOIN方式。目前三張表的鏈接方式以下所示:
無外鍵加持的連表查詢
沒有外檢關聯時,使用join關鍵字連表查詢。
result_three = session.query(Student).join(Family).join(Car).filter(Car.name=='寶馬')
從報錯信息來看,找不到外鍵關聯。這裏Car表沒有和其餘表作外鍵關聯,全部這裏找不到關聯關係。
無外鍵的join連表查詢
若是建表時使用了外鍵關聯,那麼能夠直接使用join關鍵字鏈接數據庫查詢。若是沒有外鍵關聯,也能夠連表查詢,只須要指明外鍵關係便可。
result = session.query(Student).join(Family).join(Car,Car.family_id==Family.id).filter(Car.name=='寶馬')
仍是上面的查詢語句,指明關聯字段 Car.family_id==Family.id 。
這樣就能夠完成連表查詢。
or操做
or操做經常使用於知足多個條件中的一個條件狀況下,例以下面一調語句是指知足location是地球,或者member=7的條件。只要這兩種條件其中一種知足便可。
result_four = session.query(Student.name,Family.member,House.location).join(Family).join(House).filter(or_(House.location=='地球',Family.member==7))
and操做
和or相反的,and是全部的條件必需要知足。上面的例子是指同時知足location是地球,member等於7的條件。全部or有兩個結果,and就只有一個結果。
result = session.query(Student.name,Family.member,House.location).join(Family).join(House).filter(and_(House.location=='地球',Family.member==7))
in操做
in操做是一個很方便的操做。若是沒有in的話,能夠用or一樣來完成,可是效率會低,代碼也不夠簡潔。如in_((4,5,6))等價於or_(Family.member == 4,Family.member==5,Family.member==6)。數量多的狀況下in操做是效率很高的操做。
result_six = session.query(Student.name,Family.member).join(Family).filter(Family.member.in_((4,5,6)))
offset & limit切片操做
之因此將offset和limit放在一塊兒來將,是由於這兩位經常是一塊兒出現的。對的,你猜的不錯,就是前臺分頁是使用。拋開後臺分頁工具,若是熟練使用offset和limit,本身徹底能夠寫一個後臺分頁器。
#offset。 result_seven = session.query(Student).offset(2).all()#從指定的下表開始取數據 #limit result_ten = session.query(Student).limit(2).all()#指定要取的數據的個數
~ 取反操做
result = session.query(Student.name,Family.member).join(Family).filter(~Family.member.in_((4,5,6)
between
result = session.query(Student).filter(Student.id.between(1,2))
like 統配
like的參數有兩種寫法,分別是帶%s和不帶。使用%來作通配符,帶%表示模糊查詢;不帶表示精確查詢
模糊查詢
result = session.query(Student).filter(Student.name.like('悟%'))
精確查詢
result = session.query(Student).filter(Student.name.like('悟'))
is空值判斷
result = session.query(Student).filter(Student.name.is_(None))
查詢結果類型分析
result = session.query(Student)
query查詢出來的是對象。對象能夠繼續filter過濾,也能夠all取出全部。
result = session.query(Student).all()
all()方法查詢出來的是列表。必定要主意在列表是空值的狀況下使用取值或者別的操做會形成報錯。
result = session.query(Student).filter(id==1)
filter查詢出來的是對象。對象支持鏈式操做,一個filter後面能夠繼續增長多個filter操做。
在連表查詢時,從打印出來的sql語句能夠看出join是使用了內鏈接的方式來完成的。內鏈接的鏈接方式以下,查詢兩張表中相同的部分。
外連接,也叫左鏈接。以左邊的表爲主表,右邊的表爲副表,將主表中須要的字段所有列出,而後將副表中的數據按照查詢條件與其對應起來。使用關鍵字outerjoin
Family.query.outerjoin(House).all()
右鏈接,右鏈接和左鏈接相反。1.0本不支持
全鏈接,則是將兩個表的須要的字段的數據全排列。全鏈接比較特殊,使用一個參數full=True 來完成全鏈接。1.0版本不支持
Student.query(Student.id,Family.member).join(Family,Family.id ==Student.id, full=True)
查詢的所有代碼
#coding:utf-8 from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine,and_,or_ from sqlalchemy_improve_two import Student,Family,House,Car # print "初始化數據庫引擎" engine = create_engine("mysql+mysqldb://root:123@localhost:3306/mydb?charset=utf8") # print "建立session對象" DBSession = sessionmaker(bind=engine) session = DBSession() def select_join(): # result = session.query(Student) # result = session.query(Family) # result = session.query(House) # result = session.query(Car) # print '兩張表聯表查詢' # print 'Student表joinFamily表,經過查找Family表中member字段大於6的Student表中數據' # result = session.query(Student).join(Family).filter(Family.member>6) #三張表連表查詢 # result = session.query(Student).join(Family).join(House).filter(House.location=='美剋星人') #沒有外鍵關係的join查詢。car與其餘表沒有外鍵關係 # result_three = session.query(Student).join(Family).join(Car).filter(Car.name=='寶馬') #在沒有外鍵關聯的狀況下使用join鏈接兩張表 # result = session.query(Student).join(Family).join(Car,Car.family_id==Family.id).filter(Car.name=='寶馬') #or 操做 # result = session.query(Student.name,Family.member,House.location).join(Family).join(House).filter(or_(House.location=='地球',Family.member==7)) #in操做 # result = session.query(Student.name,Family.member).join(Family).filter(Family.member.in_((4,5,6))) #offset # result = session.query(Student).offset(2) #limit # result = session.query(Student).limit(2) #~取反操做 # result = session.query(Student.name,Family.member).join(Family).filter(~Family.member.in_((4,5,6))) #between # result = session.query(Student).filter(Student.id.between(1,2)) #like # result = session.query(Student).filter(Student.name.like('悟%')) # result = session.query(Student).filter(Student.name.like('悟')) #空值判斷 # result = session.query(Student).filter(Student.name.is_(None)) # result = session.query(Student) # result = session.query(Student).all() result = session.query(Student).filter(id==1) # print 'sql語句:' # print result print 'result的數據類型:' print type(result) print '查詢結果:' for x in result: print x.id,x.name if __name__ == "__main__": select_join() # print '關閉數據庫鏈接' session.close()