摘要:上一篇文章第節(jié)關(guān)系操作級(jí)聯(lián)是在一對(duì)多關(guān)系中父表與子表進(jìn)行聯(lián)動(dòng)操作的數(shù)據(jù)庫(kù)術(shù)語。注意級(jí)聯(lián)獨(dú)立于本身針對(duì)外鍵的級(jí)聯(lián)定義。代碼執(zhí)行后數(shù)據(jù)庫(kù)表中的內(nèi)容的變化表五年二班理想路號(hào)樓表理想男靜安區(qū)女靜安區(qū)小馬哥女閘口區(qū)張三韓永躍男靜安區(qū)
上一篇文章:Python-SQLAlchemy:第3節(jié):關(guān)系操作
級(jí)聯(lián)是在一對(duì)多關(guān)系中父表與子表進(jìn)行聯(lián)動(dòng)操作的數(shù)據(jù)庫(kù)術(shù)語。因?yàn)楦副砼c子表通過外鍵關(guān)聯(lián),所以對(duì)父表或子表的增、刪、改操作會(huì)對(duì)另一張表產(chǎn)生相應(yīng)的影響。適當(dāng)?shù)睦眉?jí)聯(lián)可以開發(fā)出更優(yōu)雅、健壯的數(shù)據(jù)庫(kù)程序。本節(jié)學(xué)習(xí)SQLAlchemy中級(jí)聯(lián)的操作方法。
注意:SQLAlchemy級(jí)聯(lián)獨(dú)立于SQL本身針對(duì)外鍵的級(jí)聯(lián)定義。即使在數(shù)據(jù)庫(kù)表定義中沒有定義on delete等屬性,也不影響開發(fā)者在SQLAlchemy中使用級(jí)聯(lián)。1、級(jí)聯(lián)定義
SQLAlchemy中的級(jí)聯(lián)通過對(duì)父表中的relationship屬性定義cascade參數(shù)來實(shí)現(xiàn),代碼如下:
from sqlalchemy import Table,Column,Integer,ForeignKey,String from sqlalchemy.orm import relationship,backref from sqlalchemy.ext.declarative import declarative_base Base=declarative_base() class Class(Base): __tablename__="class" class_id=Column(Integer,primary_key=True) name=Column(String(50)) level=Column(Integer) address=Column(String(50)) students=relationship("Student",backref="class_",cascade="all") class Student(Base): __tablename__="student" student_id=Column(Integer,primary_key=True) name=Column(String(50)) age=Column(Integer) gender=Column(String(10)) address=Column(String(50)) class_id=Column(Integer,ForeignKey("class.class_id"))
上述代碼定義了班級(jí)表Class(父表)和學(xué)生表Student(子表)。一對(duì)多的關(guān)系有父表中的relationship屬性students進(jìn)行定義。relationship中的cascade參數(shù)定義了要在該關(guān)系上實(shí)現(xiàn)的級(jí)聯(lián)方法為:all。
SQLAlchemy中另外一種設(shè)置級(jí)聯(lián)的方式是在子表的relationship的backref中進(jìn)行設(shè)置。比如上述代碼可以寫為如下形式,意義保持不變:
from sqlalchemy import Table,Column,Integer,ForeignKey,String from sqlalchemy.orm import relationship,backref from sqlalchemy.ext.declarative import declarative_base Base=declarative_base() class Class(Base): __tablename__="class" class_id=Column(Integer,primary_key=True) name=Column(String(50)) level=Column(Integer) address=Column(String(50)) class Student(Base): __tablename__="student" student_id=Column(Integer,primary_key=True) name=Column(String(50)) age=Column(Integer) gender=Column(String(10)) address=Column(String(50)) class_id=Column(Integer,ForeignKey("class.class_id")) class_=relationship("Class",backref="students",cascade="all")
上述代碼沒有在父表Class中設(shè)置relationship和cascade,而是在子表中設(shè)置了。
SQLAlchemy中可選的cascade取值范圍如下表所示:
可選值 | 意義 |
---|---|
save-update | 當(dāng)一個(gè)父對(duì)象被新增到session中時(shí),該對(duì)象當(dāng)時(shí)關(guān)聯(lián)的子對(duì)象也自動(dòng)被新增到session中。 |
merge | Session.merge是一個(gè)對(duì)數(shù)據(jù)庫(kù)對(duì)象進(jìn)行新增或更新的辦法。cascade取值為merge時(shí)的意義為:當(dāng)父對(duì)象進(jìn)行merge操作時(shí),該對(duì)象當(dāng)時(shí)關(guān)聯(lián)的子對(duì)象也會(huì)被merge |
expunge | Session.expunge是一種將對(duì)象從session中移除的方法。cascade取值為expunge時(shí)的意義為:當(dāng)父對(duì)象進(jìn)行了expunge操作時(shí),該對(duì)象當(dāng)時(shí)關(guān)聯(lián)的子對(duì)象也會(huì)被從session中刪除。 |
delete | 當(dāng)父對(duì)象被delete時(shí),會(huì)自動(dòng)將該子對(duì)象刪除 |
delete-orphan | 當(dāng)子對(duì)象不再與任何父對(duì)象關(guān)聯(lián)時(shí),會(huì)自動(dòng)將該子對(duì)象刪除 |
refresh-expire | Session.expire是一種設(shè)置對(duì)象已過期、下次引用時(shí)需要從數(shù)據(jù)庫(kù)即時(shí)讀取的方法。cascade取值為refredh-expire時(shí)的意義為:當(dāng)父對(duì)象進(jìn)行了expire操作時(shí),該對(duì)象當(dāng)時(shí)關(guān)聯(lián)的子對(duì)象也進(jìn)行expire操作。 |
all | 是一個(gè)集合值,表示:save-update、merge、refresh-expire、expunge、delete同時(shí)被設(shè)置 |
多個(gè)cascade屬性可以通過逗號(hào)分隔并同時(shí)賦值給cascade。例如:
students=relationship("Student",backref="class_",cascade="save-update,merge,expunge")
在默認(rèn)情況下,任何relationship的級(jí)聯(lián)屬性都被設(shè)置為cascade="save-update,merge"。下面就常用的參數(shù):save-update、delet、delete-orphan的功能進(jìn)行舉例說明。
2、save-update級(jí)聯(lián)save-update級(jí)聯(lián)是指當(dāng)一個(gè)父對(duì)象被新增到session中時(shí),該對(duì)象當(dāng)時(shí)關(guān)聯(lián)的子對(duì)象也自動(dòng)被新增到session中。
通過如下代碼建立一個(gè)父對(duì)象class和兩個(gè)子對(duì)象students1與students2
class_=Class() student1,student2=Student(),Student() class_.students.append(student1) class_.students.append(student2)
如果父子級(jí)聯(lián)關(guān)系包含save-update,則只需要將父對(duì)象保存到session中,子對(duì)象會(huì)自動(dòng)被保存。
session.add(class_) if student1 in session: print("The student1 has been added too!")
上面代碼將會(huì)打?。?The student1 has been added too!"
技巧:”in“語句可以判斷某對(duì)象是否被關(guān)聯(lián)到了session中。已被關(guān)聯(lián)的對(duì)象在session被commit時(shí)會(huì)被寫入到視頻庫(kù)中。
即使父對(duì)象已經(jīng)被新增到session中,新關(guān)聯(lián)的子對(duì)象仍然可以被添加:
class_=Class() session.add(class_) students3=Student() if student3 in session: print("The student3 is added before append to the class_!") class_.students.append(students) if student1 in session: print("The student3 is added after append to the class_!")
這段代碼打印”The student3 is added after append to the class_!“
3、delete級(jí)聯(lián)顧名思義,delete級(jí)聯(lián)是指當(dāng)父對(duì)象被從session中刪除時(shí),其關(guān)聯(lián)的子對(duì)象也自動(dòng)被從session中delete。通過一個(gè)例子演示delete的作用,假設(shè)數(shù)據(jù)庫(kù)中class表和students表的內(nèi)容如下表所示:
class表:
class_id | name | level | address |
---|---|---|---|
1 | 三年二班 | 3 | 理想路520號(hào)1樓 |
2 | 五年一班 | 5 | 理想路520號(hào)3樓 |
3 | 五年二班 | 5 | 理想路520號(hào)3樓 |
student表:
student_id | class_id | name | age | gender | address | contactor |
---|---|---|---|---|---|---|
1 | 1 | 理想 | 10 | 男 | 靜安區(qū) | Null |
2 | 1 | mark | 10 | 女 | 靜安區(qū) | Null |
3 | 1 | 小馬哥 | 9 | 女 | 閘口區(qū) | 張三 |
4 | 2 | 張苗 | 10 | 男 | 寶山區(qū) | NULL |
5 | 2 | 小黑 | 12 | 女 | 靜安區(qū) | 李四 |
6 | 2 | 喵喵 | 11 | 男 | 閘北區(qū) | NULL |
7 | 1 | 韓永躍 | 10 | 男 | 靜安區(qū) | NULL |
8 | 3 | 小鏡鏡 | 12 | 男 | 閘北區(qū) | NULL |
9 | 3 | 小鏡子 | 12 | 女 | 寶山區(qū) | NULL |
從例表中可知,系統(tǒng)中有3個(gè)班級(jí),他們分別有4、3、2個(gè)學(xué)生。如果SQLAlchemy中沒有把它們的relationship的cascade設(shè)置為delete,則刪除父表內(nèi)容不會(huì)刪除相應(yīng)的子表內(nèi)容,而是把子表的相應(yīng)外鍵設(shè)置為空。比如:
class_=session.query(Class).filter(name="三年二班").first() #三年二班的class_id為1 session.delete(class_) #刪除class_id為1的班級(jí)
當(dāng)cascade不包含delete時(shí),上述代碼中的delete語句相當(dāng)于執(zhí)行了如下SQL語句:
UPDATE student SET class_id=None WHERE class_id=1; DELETE FROM class WHERE class_id=1; COMMIT;
執(zhí)行后數(shù)據(jù)表class和student的內(nèi)容變化如下所示:
class表:
class_id | name | level | address |
---|---|---|---|
2 | 五年一班 | 5 | 理想路520號(hào)3樓 |
3 | 五年二班 | 5 | 理想路520號(hào)3樓 |
student表:
student_id | class_id | name | age | gender | address | contactor |
---|---|---|---|---|---|---|
1 | NULL | 理想 | 10 | 男 | 靜安區(qū) | Null |
2 | NULL | mark | 10 | 女 | 靜安區(qū) | Null |
3 | NULL | 小馬哥 | 9 | 女 | 閘口區(qū) | 張三 |
4 | 2 | 張苗 | 10 | 男 | 寶山區(qū) | NULL |
5 | 2 | 小黑 | 12 | 女 | 靜安區(qū) | 李四 |
6 | 2 | 喵喵 | 11 | 男 | 閘北區(qū) | NULL |
7 | 1 | 韓永躍 | 10 | 男 | 靜安區(qū) | NULL |
8 | 3 | 小鏡鏡 | 12 | 男 | 閘北區(qū) | NULL |
9 | 3 | 小鏡子 | 12 | 女 | 寶山區(qū) | NULL |
此時(shí)將表定義中的relationship的cascade屬性設(shè)置為delete:
students=relationship("Student",backref="class",cascade="delete")
現(xiàn)在通過如下語句刪除“五年一班”:
class_=session.query(Class).filter(name="五年一班").first() #五年一班的class_id為2 session.delete(class_) #刪除class_id為2的班級(jí)
當(dāng)cascade包含“delete”時(shí),上述代碼中的delete語句相當(dāng)于執(zhí)行了如下SQL語句:
DELETE FROM student WHERE class=2; DELETE FROM class WHERE class=2; COMMIT;
執(zhí)行后數(shù)據(jù)庫(kù)表class和student的內(nèi)容變化如下表所示:
class表:
class_id | name | level | address |
---|---|---|---|
3 | 五年二班 | 5 | 理想路520號(hào)3樓 |
student表:
student_id | class_id | name | age | gender | address | contactor |
---|---|---|---|---|---|---|
1 | NULL | 理想 | 10 | 男 | 靜安區(qū) | Null |
2 | NULL | mark | 10 | 女 | 靜安區(qū) | Null |
3 | NULL | 小馬哥 | 9 | 女 | 閘口區(qū) | 張三 |
7 | NULL | 韓永躍 | 10 | 男 | 靜安區(qū) | NULL |
8 | 3 | 小鏡鏡 | 12 | 男 | 閘北區(qū) | NULL |
9 | 3 | 小鏡子 | 12 | 女 | 寶山區(qū) | NULL |
delete-orphan級(jí)聯(lián)是指當(dāng)子對(duì)象不再與任何父對(duì)象關(guān)聯(lián)時(shí),會(huì)自動(dòng)將該子對(duì)象刪除。設(shè)置父表與子表的relationship中的cascade包含“delete-orphan”:
students=relationship("Student",backref="class",cascade="delete-orphan")
通過如下代碼將于班級(jí)“五年一班”關(guān)聯(lián)的學(xué)生全部脫離:
class_=session.query(Class).filter(name="五年二班").first() unattachedStudent=[] while len(class_.students)>0: unattachedStudent.append(class_.students.pop()) #與父對(duì)象脫離 session.commit #顯示地提交事務(wù)
上述代碼中沒有顯示地刪除任何學(xué)生,但由于使用了delete-orphan級(jí)聯(lián),所以被脫離出班級(jí)對(duì)象的學(xué)生會(huì)在session事務(wù)提交時(shí)會(huì)自動(dòng)從數(shù)據(jù)庫(kù)中刪除。代碼執(zhí)行后數(shù)據(jù)庫(kù)表中的內(nèi)容的變化:
class表:
class_id | name | level | address |
---|---|---|---|
3 | 五年二班 | 5 | 理想路520號(hào)3樓 |
student表:
student_id | class_id | name | age | gender | address | contactor |
---|---|---|---|---|---|---|
1 | NULL | 理想 | 10 | 男 | 靜安區(qū) | Null |
2 | NULL | mark | 10 | 女 | 靜安區(qū) | Null |
3 | NULL | 小馬哥 | 9 | 女 | 閘口區(qū) | 張三 |
7 | NULL | 韓永躍 | 10 | 男 | 靜安區(qū) | NULL |
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/44879.html
摘要:本節(jié)圍繞在中如何定義關(guān)系及如何使用關(guān)系進(jìn)行查詢進(jìn)行講解,使讀者能夠快速掌握的關(guān)系操作。班級(jí)與學(xué)生為一對(duì)多關(guān)系,班級(jí)與老師之間為多對(duì)多關(guān)系。三年二班多對(duì)多關(guān)系的使用通過關(guān)聯(lián)模型實(shí)現(xiàn),在其中分別設(shè)置模型和的外鍵,并且在父模型中設(shè)置相應(yīng)的實(shí)現(xiàn)。 上一篇文章:Python-SQLAlchemy:第2節(jié):查詢條件設(shè)置下一篇文章:Python-SQLAlchemy:第4節(jié):級(jí)聯(lián) 關(guān)系數(shù)據(jù)庫(kù)是建立...
摘要:上一篇文章第節(jié)入門下一篇文章第節(jié)關(guān)系操作在實(shí)際編程中需要根據(jù)各種不同的條件查詢數(shù)據(jù)庫(kù)記錄,查詢條件被稱為過濾器。通配符用百分號(hào)表示。以下條語句查詢結(jié)果相同,都是為的記錄。引入或邏輯關(guān)鍵字查詢是或者為的記錄,返回結(jié)果為為的記錄 上一篇文章:Python-SQLAlchemy:第1節(jié):SQLAlchemy入門下一篇文章:Python-SQLAlchemy:第3節(jié):關(guān)系操作 在實(shí)際編程中需...
摘要:下一篇文章第節(jié)查詢條件設(shè)置是編程語言下的一款開源軟件。提供了工具包及對(duì)象關(guān)系映射工具,使用許可證發(fā)行。在關(guān)閉連接時(shí)會(huì)自動(dòng)進(jìn)行事務(wù)提交操作。引入多條件查詢時(shí)使用。由于上下文函數(shù)退出時(shí)會(huì)自動(dòng)提交事務(wù),所以無需顯示的調(diào)用使新增生效。 下一篇文章:Python-SQLAlchemy:第2節(jié):查詢條件設(shè)置 SQLAlchemy是Python編程語言下的一款開源軟件。提供了SQL工具包及對(duì)象關(guān)系...
摘要:因?yàn)槭枪ぷ髟谝粋€(gè)內(nèi)部,有時(shí)候我們可能不小心做了一些誤刪除的操作,可以回滾。我們先修改的用戶名為,然后重新添加一個(gè)新,但是記住這個(gè)時(shí)候我們還沒有。集合類型可以是各種合法類型,比如,但是默認(rèn)集合是一個(gè)。 官方文檔 Initialization # 檢查是否已經(jīng)安裝以及版本號(hào) >>> import sqlalchemy >>> sqlalchemy.__version__ ’1.1.4‘ ...
閱讀 3461·2023-04-26 02:48
閱讀 1465·2021-10-11 10:57
閱讀 2490·2021-09-23 11:35
閱讀 1196·2021-09-06 15:02
閱讀 3294·2019-08-30 15:54
閱讀 1612·2019-08-30 15:44
閱讀 879·2019-08-30 15:44
閱讀 988·2019-08-30 12:52