天天看點

python sqlalchemy操作_Python-SQLAlchemy:第3節:關系操作

關系資料庫是建立在關系模型基礎上的資料庫,是以表之間的關系在資料庫程式設計中尤為重要。本節圍繞在SQLAlchemy中如何定義關系及如何使用關系進行查詢進行講解,使讀者能夠快速掌握SQLAlchemy的關系操作。

1、案例

設計3個實體表:班級表class、學生表student、老師表teacher和1個關系表:class_teacher。班級與學生為一對多關系,班級與老師之間為多對多關系。

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_teachers=relationship("ClassTeacher",backref="class")

students=relationship("Student",backref="class")

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.id'))

class Teacher(Base):

__tablename__='teacher'

teacher_id=Column(Integer,primary_key=True)

name=Column(String(50))

gender=Column(String(10))

telephone=Column(String(50))

address=Column(String(50))

class_teachers=relationship("ClassTeacher",backref="teacher")

class ClassTeacher(Base):

__tablename__='class_teacher'

teacher_id=Column(Integer,ForeignKey('teacher.teacher_id'),primary_key=True)

class_id=Column(Integer,ForeignKey("class.id"),primary_key=True)

代碼中用了4個SQLAlchemy模型對4個表進行了定義,其中與關系定義相關的部分如下:

外鍵設定:在列的定義中,為Column傳入ForeignKey進行外鍵設定。

class_id=Column(Integer,ForeignKey('class.id'))

關系設定:通過relationship關鍵字在父模型中建立對字表的引用,例如Class模型中的關系設定如下:

students=relationship("Student",backref="calss")

其中的backref參數為可選參數,如果設定backref,則此語句同時設定了 從父表對子表的引用。

一對多關系的使用:以後可以直接通過該students屬性獲得相關班級中所有學生的資訊。如下代碼可以列印班級【三年二班】的所有學生資訊。

class=session.query(Class).filter(Clss.name=="三年二班").first()

for student in class_.students:

print(student)

多對多關系的使用:通過關聯模型ClassTeacher實作,在其中分别設定模型Class和Teacher的外鍵,并且在父模型中設定相應的relationship實作。多對多關系也可以想象成一個關聯表,分别對兩個父表實作了多對一的關系。班級與老師之間為多對多的關系,如下代碼可以列印班級【三年二班】中所有老師的資訊

class=session.query(Class).filter(Class.name=="三年二班").first()

for class_teacher in class_.class_teachers:

teacher=class_teacher.teacher

print(teacher)

上述代碼中class_teacher.teacher是在模型teacher中針對ClassTeacher定義的反向引用。

2、連接配接查詢

在實際開發中,有了關系就必不可少地會有多表連接配接查詢的需求。下面通過實際例子示範如果進行多表連接配接查詢。

在查詢語句中可以使用join關鍵字進行連接配接查詢,列印出所有三年級學生的姓名:

students=session.query(Student).join(Class).filter(Class.level==3).all()

for student in students:

print(student.namr)

上述查詢函數會自動把外鍵關系作為連接配接條件,該查詢被SQLAlchemy自動翻譯為如下SQL語句并執行:

SELECT student.student_id AS student_student_id,

student.name AS student.name,

student.age AS student.age,

student.gender AS student.gender,

student.address AS student.address,

student.class_id AS student_class_id

FROM student JOIN class ON student.class_id=class.class_id

WHERE class.leve=?

(3,)

如果需要将被連接配接表的内心同樣列印出來,則可以在query中指定多個表對象。

下面的語句在列印出所有三年級學生姓名的同時,列印出其所在班級的名字。

for student,class_ in session.query(Student,Class).join(Class).filter(Class.level==3).all():

print(student.name,class_.name)

上述查詢函數會自動把外鍵關系作為連接配接條件,該查詢被SQLAlchemy自動翻譯為如下SQL語句并執行:

SELECT student.student_id AS student_student_id,

student.name AS student.name,

student.age AS student.age,

student.gender AS student.gender,

student.address AS student.address,

student.class_id AS student_class_id,

class.class_id AS class_class_id,

class.name AS class_name,

class.level AS class_level,

class.address AS class_location

FROM student JOIN class ON student.class_id=class.class_id

WHERE class.leve=?

(3,)

如果需要用除外鍵外的其他字段作為連接配接條件,則需要開發者在join中自行設定。下面列印出所有班級的address與學生的address相同的學生的姓名:

for student_name, in session.query(Student.name).join(Class,Class.address==Student.address).filter(Class.level==3).all():

print(student_name)

上述查詢函數根據開發者指定的語句作為連接配接條件,并且因為直接指定了被查詢的字段,是以減少了實際SQL中的被查詢字段,提高了性能。該查詢被SQLAlchemy自動翻譯為如下SQL語句執行:

SELECT student.name AS student_name, FROM student JOIN class ON student.address=class.address