ORM
ORM,对象关系映射,对象和关系之间的映射,使用面向对象的方式来操作数据库。
关系模型和Python对象之间的映射 table => class ,表映射为类 row => object ,行映射为实例 column => property ,字段映射为属性
SQLALchemy
SQLALchemy是一个ORM框架
安装
pip install sqlalchemy
文档
官方文档:http://docs.sqlalchemy.org/en/latest/
开发
SQLALchemy内部使用了连接池
创建连接
数据库连接的事情,交给引擎
dialect
+ driver
://username
:password@host
:port
/database
mysql
+ mysqldb
://<user
>:<password
>@
<host
>[:<port
>]/<dbname
>
engine
= sqlalchemy
.create_engine
("mysql+mysqldb://lee:123456@192.168.174.143:3306/test")
mysql
+pymysql
://<username
>:<password
>@
<host
>/<dbname
>[?
<options
>]
engine
= sqlalchemy
.create_engine
("mysql+pymysql://lee:123456@192.168.174.143:3306/test")
engine
= sqlalchemy
.create_engine
("mysql+pymysql://lee:123456@192.168.174.143:3306/test", echo
=True)
echo
= True
引擎是否打印执行的语句,调试的时候打开很方便。
lazy connecting
:懒连接。创建引擎并不会马上连接数据库,直到让数据库执行任务时才连接。
Declare a Mapping创建映射
创建基类
from sqlalchemy
.ext
.declarative
import declarative_base
Base
= declarative_base
()
创建实体类
CREATE TABLE student
(
id INTEGER NOT NULL AUTO_INCREMENT
,
name VARCHAR
(64) NOT NULL
,
age INTEGER
,
PRIMARY KEY
(id)
)
class Student(Base
):
__tablename__
= 'student'
id = Column
(Integer
, primary_key
=True, autoincrement
=True)
name
= Column
(String
(64), nullable
=False)
age
= Column
(Integer
)
def __repr__(self
):
return "{} id={} name={} age={}".format(self
.__class__
.__name__
, self
.id, self
.name
, self
.age
)
实例化
s
= Student
(name
='tom')
print(s
.name
)
s
.age
= 20
print(s
.age
)
创建表
可以使用SQLALchemy来创建、删除表
Base
.metadata
.drop_all
(engine
)
Base
.metadata
.create_all
(engine
)
生产环境很少这样创建表,都是系统上线的时候由脚本生成。 生产环境很少删除表,宁可废弃都不能删除。
创建会话session
在一个会话中操作数据库,会话建立在连接上,连接被引擎管理。 当第一次使用数据库时,从引擎维护的连接池中获取一个连接使用。
Session
= sessionmaker
(bind
=engine
)
session
= Session
()
session对象线程不安全。所以不同线程应该使用不用的session对象。 Session类和engine有一个就行了。
CRUD操作
增
add(): 增加一个对象 add_all(): 可迭代对象,元素是对象
from sqlalchemy
import Column
, Integer
, String
, create_engine
from sqlalchemy
.orm
import sessionmaker
from sqlalchemy
.ext
.declarative
import declarative_base
USER
= 'lee'
PASSWORD
= '123456'
HOST
= '192.168.174.143'
PORT
= 3306
DATABASE
= 'test'
constr
= 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USER
, PASSWORD
, HOST
, PORT
, DATABASE
)
engine
= create_engine
(constr
, echo
=True)
Base
= declarative_base
()
class Student(Base
):
__tablename__
= 'student'
id = Column
(Integer
, primary_key
=True, autoincrement
=True)
name
= Column
(String
(64), nullable
=False)
age
= Column
(Integer
)
def __repr__(self
):
return "<{} {} {} {}>".format(self
.__class__
.__name__
, self
.id, self
.name
, self
.age
)
Base
.metadata
.drop_all
(engine
)
Base
.metadata
.create_all
(engine
)
Session
= sessionmaker
(bind
=engine
)
session
= Session
()
s
= Student
(name
='tom')
s
.age
= 20
print(s
)
session
.add
(s
)
print(s
, '++++++++++')
session
.commit
()
print(s
)
print('====================')
try:
session
.add_all
([s
])
print(s
)
session
.commit
()
print(s
)
except:
session
.rollback
()
print('roll back')
raise
2019-09-24 22:22:39,573 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
2019-09-24 22:22:39,575 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,578 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names'
2019-09-24 22:22:39,580 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,584 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2019-09-24 22:22:39,585 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,588 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8mb4' and `Collation` = 'utf8mb4_bin'
2019-09-24 22:22:39,590 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,593 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
2019-09-24 22:22:39,595 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,597 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
2019-09-24 22:22:39,599 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,603 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1
2019-09-24 22:22:39,605 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,608 INFO sqlalchemy.engine.base.Engine DESCRIBE `student`
2019-09-24 22:22:39,609 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,616 INFO sqlalchemy.engine.base.Engine
DROP TABLE student
2019-09-24 22:22:39,618 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,623 INFO sqlalchemy.engine.base.Engine COMMIT
2019-09-24 22:22:39,627 INFO sqlalchemy.engine.base.Engine DESCRIBE `student`
2019-09-24 22:22:39,629 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,633 INFO sqlalchemy.engine.base.Engine ROLLBACK
2019-09-24 22:22:39,636 INFO sqlalchemy.engine.base.Engine
CREATE TABLE student (
id INTEGER NOT NULL AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
age INTEGER,
PRIMARY KEY (id)
)
2019-09-24 22:22:39,639 INFO sqlalchemy.engine.base.Engine {}
2019-09-24 22:22:39,643 INFO sqlalchemy.engine.base.Engine COMMIT
<Student None tom 20>
<Student None tom 20> ++++++++++
2019-09-24 22:22:39,649 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-09-24 22:22:39,652 INFO sqlalchemy.engine.base.Engine INSERT INTO student (name, age) VALUES (%(name)s, %(age)s)
2019-09-24 22:22:39,654 INFO sqlalchemy.engine.base.Engine {'name': 'tom', 'age': 20}
2019-09-24 22:22:39,659 INFO sqlalchemy.engine.base.Engine COMMIT
2019-09-24 22:22:39,666 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-09-24 22:22:39,668 INFO sqlalchemy.engine.base.Engine SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age
FROM student
WHERE student.id = %(param_1)s
2019-09-24 22:22:39,669 INFO sqlalchemy.engine.base.Engine {'param_1': 1}
<Student 1 tom 20>
====================
<Student 1 tom 20>
2019-09-24 22:22:39,673 INFO sqlalchemy.engine.base.Engine COMMIT
2019-09-24 22:22:39,680 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-09-24 22:22:39,683 INFO sqlalchemy.engine.base.Engine SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age
FROM student
WHERE student.id = %(param_1)s
2019-09-24 22:22:39,684 INFO sqlalchemy.engine.base.Engine {'param_1': 1}
<Student 1 tom 20>
add_all()方法不会提交成功的,因为s成功提交后,s的主键就有了值,所以,只要s没有修改过,就认为没有改动。s变化了,就可以提交修改了。
简单查询
使用query()方法,返回一个Query对象
students
= session
.query
(Student
)
print(students
)
for student
in students
:
print(student
)
print('========================')
student
= session
.query
(Student
).get
(2)
print(student
)
SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age
FROM student
2019-09-24 16:58:13,951 INFO sqlalchemy.engine.base.Engine SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age
FROM student
2019-09-24 16:58:13,953 INFO sqlalchemy.engine.base.Engine {}
<Student 1 tom 20>
========================
2019-09-24 16:58:13,960 INFO sqlalchemy.engine.base.Engine SELECT student.id AS student_id, student.name AS student_name, student.age AS student_age
FROM student
WHERE student.id = %(param_1)s
2019-09-24 16:58:13,962 INFO sqlalchemy.engine.base.Engine {'param_1': 2}
None
query方法将实体类传入,返回类的对象可迭代对象,这时候并不查询。迭代它就执行SQL来查询数据库,封装数据到指定类的实例。 get方法使用主键查询,返回一条传入类的一个实例。
改
student
= session
.query
(Student
).get
(1)
print(student
)
student
.name
= 'sam'
student
.age
= 30
print(student
)
session
.add
(student
)
session
.commit
()
<Student 1 tom 20>
<Student 1 sam 30>
2019-09-24 17:03:28,533 INFO sqlalchemy.engine.base.Engine UPDATE student SET name=%(name)s, age=%(age)s WHERE student.id = %(student_id)s
2019-09-24 17:03:28,534 INFO sqlalchemy.engine.base.Engine {'name': 'sam', 'age': 30, 'student_id': 1}
2019-09-24 17:03:28,538 INFO sqlalchemy.engine.base.Engine COMMIT
先查,修改,再提交更改(commit)
删除
try:
student
= Student
(id=2, name
='sam', age
=40)
session
.delete
(student
)
session
.commit
()
except Exception
as e
:
session
.rollback
()
print('=========================')
print(e
)
2019-09-24 22:13:05,757 INFO sqlalchemy.engine.base.Engine ROLLBACK
=========================
Instance '<Student at 0x1b4e9caeba8>' is not persisted
try:
student
= Student
(id=2, name
='sam', age
=40)
session
.add
(student
)
session
.commit
()
except Exception
as e
:
session
.rollback
()
print('=========================')
print(e
)
2019-09-24 22:23:07,493 INFO sqlalchemy.engine.base.Engine INSERT INTO student (id, name, age) VALUES (%(id)s, %(name)s, %(age)s)
2019-09-24 22:23:07,494 INFO sqlalchemy.engine.base.Engine {'id': 2, 'name': 'sam', 'age': 40}
2019-09-24 22:23:07,500 INFO sqlalchemy.engine.base.Engine COMMIT
try:
student
= Student
(id=2, name
='sam', age
=40)
session
.delete
(student
)
session
.commit
()
except Exception
as e
:
session
.rollback
()
print('=========================')
print(e
)
=========================
Instance '<Student at 0x1b4ec475ef0>' is not persisted
from sqlalchemy
.ext
.declarative
import declarative_base
from sqlalchemy
import Column
,Integer
,String
,Date
,Enum
,ForeignKey
,create_engine
from sqlalchemy
.orm
import sessionmaker
import enum
Base
= declarative_base
()
connstr
= "{}://{}:{}@{}:{}/{}".format('mysql+pymysql','lee','123456','192.168.174.144', 3306, 'test')
engine
= create_engine
(connstr
, echo
=True)
Session
= sessionmaker
(bind
=engine
)
session
= Session
()
class MyEnum(enum
.Enum
):
M
= 'M'
F
= 'F'
class Employee(Base
):
__tablename__
= 'employees'
emp_no
= Column
(Integer
,primary_key
=True)
birth_date
= Column
(Date
, nullable
=False)
first_name
= Column
(String
(14), nullable
=False)
last_name
= Column
(String
(16), nullable
=False)
gender
= Column
(Enum
(MyEnum
), nullable
=False)
hire_date
= Column
(Date
, nullable
=False)
def __repr__(self
):
return "{} no={} name={} {} gender={}".format(self
.__class__
.__name__
, self
.emp_no
, self
.first_name
, self
.last_name
, self
.gender
.value
)
def show(emps
):
for x
in emps
:
print(x
)
print('=============================\n')
emps
= session
.query
(Employee
).filter(Employee
.emp_no
> 10015)
show
(emps
)
from sqlalchemy
import or_
, and_
, not_
emps
= session
.query
(Employee
).filter(Employee
.emp_no
> 10015).filter(Employee
.gender
== MyEnum
.F
)
show
(emps
)
emps
= session
.query
(Employee
).filter(Employee
.emp_no
> 10015, Employee
.emp_no
< 10020)
show
(emps
)
emps
= session
.query
(Employee
).filter(and_
(Employee
.emp_no
> 10016, Employee
.emp_no
< 10020))
show
(emps
)
emps
= session
.query
(Employee
).filter((Employee
.emp_no
> 10017) & (Employee
.emp_no
< 10020))
show
(emps
)
emps
= session
.query
(Employee
).filter((Employee
.emp_no
> 10018) | (Employee
.emp_no
< 10016))
show
(emps
)
emps
= session
.query
(Employee
).filter(or_
(Employee
.emp_no
< 10005, Employee
.emp_no
> 10018))
show
(emps
)
emps
= session
.query
(Employee
).filter(not_
(Employee
.emp_no
> 10010))
show
(emps
)
emps
= session
.query
(Employee
).filter(~(Employee
.emp_no
> 10010))
show
(emps
)
emplist
= [10010, 10015, 10016]
emps
= session
.query
(Employee
).filter(Employee
.emp_no
.in_
(emplist
))
show
(emps
)
emps
= session
.query
(Employee
).filter(Employee
.last_name
.like
('P%'))
show
(emps
)
emps
= session
.query
(Employee
).filter(Employee
.emp_no
> 10010).order_by
(Employee
.emp_no
)
show
(emps
)
emps
= session
.query
(Employee
).filter(Employee
.emp_no
> 10010).order_by
(Employee
.emp_no
.desc
())
show
(emps
)
print('++++++++++++++++++++++++++++')
emps
= session
.query
(Employee
).filter(Employee
.emp_no
> 10010).order_by
(Employee
.last_name
).order_by
(Employee
.emp_no
.desc
())
show
(emps
)
emps
= session
.query
(Employee
).limit
(4)
show
(emps
)
emps
= session
.query
(Employee
).limit
(5).offset
(18)
show
(emps
)
2019-09-25 21:10:28,666 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
2019-09-25 21:10:28,667 INFO sqlalchemy.engine.base.Engine {}
2019-09-25 21:10:28,672 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'lower_case_table_names'
2019-09-25 21:10:28,674 INFO sqlalchemy.engine.base.Engine {}
2019-09-25 21:10:28,677 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2019-09-25 21:10:28,679 INFO sqlalchemy.engine.base.Engine {}
2019-09-25 21:10:28,682 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8mb4' and `Collation` = 'utf8mb4_bin'
2019-09-25 21:10:28,683 INFO sqlalchemy.engine.base.Engine {}
2019-09-25 21:10:28,687 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
2019-09-25 21:10:28,690 INFO sqlalchemy.engine.base.Engine {}
2019-09-25 21:10:28,696 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
2019-09-25 21:10:28,698 INFO sqlalchemy.engine.base.Engine {}
2019-09-25 21:10:28,701 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1
2019-09-25 21:10:28,703 INFO sqlalchemy.engine.base.Engine {}
2019-09-25 21:10:28,706 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-09-25 21:10:28,709 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s
2019-09-25 21:10:28,711 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10015}
Employee no=10016 name=Kazuhito Cappelletti gender=M
Employee no=10017 name=Cristinel Bouloucos gender=F
Employee no=10018 name=Kazuhide Peha gender=F
Employee no=10019 name=Lillian Haddadi gender=M
Employee no=10020 name=Mayuko Warwick gender=M
=============================
2019-09-25 21:10:28,722 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s AND employees.gender = %(gender_1)s
2019-09-25 21:10:28,724 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10015, 'gender_1': 'F'}
Employee no=10017 name=Cristinel Bouloucos gender=F
Employee no=10018 name=Kazuhide Peha gender=F
=============================
2019-09-25 21:10:28,730 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s AND employees.emp_no < %(emp_no_2)s
2019-09-25 21:10:28,732 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10015, 'emp_no_2': 10020}
Employee no=10016 name=Kazuhito Cappelletti gender=M
Employee no=10017 name=Cristinel Bouloucos gender=F
Employee no=10018 name=Kazuhide Peha gender=F
Employee no=10019 name=Lillian Haddadi gender=M
=============================
2019-09-25 21:10:28,739 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s AND employees.emp_no < %(emp_no_2)s
2019-09-25 21:10:28,741 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10016, 'emp_no_2': 10020}
Employee no=10017 name=Cristinel Bouloucos gender=F
Employee no=10018 name=Kazuhide Peha gender=F
Employee no=10019 name=Lillian Haddadi gender=M
=============================
2019-09-25 21:10:28,747 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s AND employees.emp_no < %(emp_no_2)s
2019-09-25 21:10:28,748 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10017, 'emp_no_2': 10020}
Employee no=10018 name=Kazuhide Peha gender=F
Employee no=10019 name=Lillian Haddadi gender=M
=============================
2019-09-25 21:10:28,755 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s OR employees.emp_no < %(emp_no_2)s
2019-09-25 21:10:28,757 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10018, 'emp_no_2': 10016}
Employee no=10001 name=Georgi Facello gender=M
Employee no=10002 name=Bezalel Simmel gender=F
Employee no=10003 name=Parto Bamford gender=M
Employee no=10004 name=Chirstian Koblick gender=M
Employee no=10005 name=Kyoichi Maliniak gender=M
Employee no=10006 name=Anneke Preusig gender=F
Employee no=10007 name=Tzvetan Zielinski gender=F
Employee no=10008 name=Saniya Kalloufi gender=M
Employee no=10009 name=Sumant Peac gender=F
Employee no=10010 name=Duangkaew Piveteau gender=F
Employee no=10011 name=Mary Sluis gender=F
Employee no=10012 name=Patricio Bridgland gender=M
Employee no=10013 name=Eberhardt Terkki gender=M
Employee no=10014 name=Berni Genin gender=M
Employee no=10015 name=Guoxiang Nooteboom gender=M
Employee no=10019 name=Lillian Haddadi gender=M
Employee no=10020 name=Mayuko Warwick gender=M
=============================
2019-09-25 21:10:28,769 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no < %(emp_no_1)s OR employees.emp_no > %(emp_no_2)s
2019-09-25 21:10:28,770 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10005, 'emp_no_2': 10018}
Employee no=10001 name=Georgi Facello gender=M
Employee no=10002 name=Bezalel Simmel gender=F
Employee no=10003 name=Parto Bamford gender=M
Employee no=10004 name=Chirstian Koblick gender=M
Employee no=10019 name=Lillian Haddadi gender=M
Employee no=10020 name=Mayuko Warwick gender=M
=============================
2019-09-25 21:10:28,777 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no <= %(emp_no_1)s
2019-09-25 21:10:28,778 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
Employee no=10001 name=Georgi Facello gender=M
Employee no=10002 name=Bezalel Simmel gender=F
Employee no=10003 name=Parto Bamford gender=M
Employee no=10004 name=Chirstian Koblick gender=M
Employee no=10005 name=Kyoichi Maliniak gender=M
Employee no=10006 name=Anneke Preusig gender=F
Employee no=10007 name=Tzvetan Zielinski gender=F
Employee no=10008 name=Saniya Kalloufi gender=M
Employee no=10009 name=Sumant Peac gender=F
Employee no=10010 name=Duangkaew Piveteau gender=F
=============================
2019-09-25 21:10:28,787 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no <= %(emp_no_1)s
2019-09-25 21:10:28,788 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
Employee no=10001 name=Georgi Facello gender=M
Employee no=10002 name=Bezalel Simmel gender=F
Employee no=10003 name=Parto Bamford gender=M
Employee no=10004 name=Chirstian Koblick gender=M
Employee no=10005 name=Kyoichi Maliniak gender=M
Employee no=10006 name=Anneke Preusig gender=F
Employee no=10007 name=Tzvetan Zielinski gender=F
Employee no=10008 name=Saniya Kalloufi gender=M
Employee no=10009 name=Sumant Peac gender=F
Employee no=10010 name=Duangkaew Piveteau gender=F
=============================
2019-09-25 21:10:28,798 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no IN (%(emp_no_1)s, %(emp_no_2)s, %(emp_no_3)s)
2019-09-25 21:10:28,800 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010, 'emp_no_2': 10015, 'emp_no_3': 10016}
Employee no=10010 name=Duangkaew Piveteau gender=F
Employee no=10015 name=Guoxiang Nooteboom gender=M
Employee no=10016 name=Kazuhito Cappelletti gender=M
=============================
2019-09-25 21:10:28,808 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.last_name LIKE %(last_name_1)s
2019-09-25 21:10:28,810 INFO sqlalchemy.engine.base.Engine {'last_name_1': 'P%'}
Employee no=10006 name=Anneke Preusig gender=F
Employee no=10009 name=Sumant Peac gender=F
Employee no=10010 name=Duangkaew Piveteau gender=F
Employee no=10018 name=Kazuhide Peha gender=F
=============================
2019-09-25 21:10:28,816 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s ORDER BY employees.emp_no
2019-09-25 21:10:28,818 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
Employee no=10011 name=Mary Sluis gender=F
Employee no=10012 name=Patricio Bridgland gender=M
Employee no=10013 name=Eberhardt Terkki gender=M
Employee no=10014 name=Berni Genin gender=M
Employee no=10015 name=Guoxiang Nooteboom gender=M
Employee no=10016 name=Kazuhito Cappelletti gender=M
Employee no=10017 name=Cristinel Bouloucos gender=F
Employee no=10018 name=Kazuhide Peha gender=F
Employee no=10019 name=Lillian Haddadi gender=M
Employee no=10020 name=Mayuko Warwick gender=M
=============================
2019-09-25 21:10:28,827 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s ORDER BY employees.emp_no DESC
2019-09-25 21:10:28,828 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
Employee no=10020 name=Mayuko Warwick gender=M
Employee no=10019 name=Lillian Haddadi gender=M
Employee no=10018 name=Kazuhide Peha gender=F
Employee no=10017 name=Cristinel Bouloucos gender=F
Employee no=10016 name=Kazuhito Cappelletti gender=M
Employee no=10015 name=Guoxiang Nooteboom gender=M
Employee no=10014 name=Berni Genin gender=M
Employee no=10013 name=Eberhardt Terkki gender=M
Employee no=10012 name=Patricio Bridgland gender=M
Employee no=10011 name=Mary Sluis gender=F
=============================
++++++++++++++++++++++++++++
2019-09-25 21:10:28,837 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
WHERE employees.emp_no > %(emp_no_1)s ORDER BY employees.last_name, employees.emp_no DESC
2019-09-25 21:10:28,838 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
Employee no=10017 name=Cristinel Bouloucos gender=F
Employee no=10012 name=Patricio Bridgland gender=M
Employee no=10016 name=Kazuhito Cappelletti gender=M
Employee no=10014 name=Berni Genin gender=M
Employee no=10019 name=Lillian Haddadi gender=M
Employee no=10015 name=Guoxiang Nooteboom gender=M
Employee no=10018 name=Kazuhide Peha gender=F
Employee no=10011 name=Mary Sluis gender=F
Employee no=10013 name=Eberhardt Terkki gender=M
Employee no=10020 name=Mayuko Warwick gender=M
=============================
2019-09-25 21:10:28,847 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
LIMIT %(param_1)s
2019-09-25 21:10:28,849 INFO sqlalchemy.engine.base.Engine {'param_1': 4}
Employee no=10001 name=Georgi Facello gender=M
Employee no=10002 name=Bezalel Simmel gender=F
Employee no=10003 name=Parto Bamford gender=M
Employee no=10004 name=Chirstian Koblick gender=M
=============================
2019-09-25 21:10:28,857 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
LIMIT %(param_1)s, %(param_2)s
2019-09-25 21:10:28,858 INFO sqlalchemy.engine.base.Engine {'param_1': 18, 'param_2': 5}
Employee no=10019 name=Lillian Haddadi gender=M
Employee no=10020 name=Mayuko Warwick gender=M
=============================
消费者方法
消费者方法调用后,Query对象(可迭代)就转换成了一个容器。
emps
= session
.query
(Employee
)
print(len(list(emps
)))
print(emps
.count
())
print(emps
.all())
print(emps
.first
())
print('+++++++++++++++++++++++++++++')
print(emps
.limit
(1).one
())
session
.query
(Employee
).filter(Employee
.emp_no
> 10018).delete
()
2019-09-25 21:48:48,856 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
2019-09-25 21:48:48,858 INFO sqlalchemy.engine.base.Engine {}
20
2019-09-25 21:48:48,868 INFO sqlalchemy.engine.base.Engine SELECT count(*) AS count_1
FROM (SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees) AS anon_1
2019-09-25 21:48:48,870 INFO sqlalchemy.engine.base.Engine {}
20
2019-09-25 21:48:48,875 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
2019-09-25 21:48:48,877 INFO sqlalchemy.engine.base.Engine {}
[Employee no=10001 name=Georgi Facello gender=M, Employee no=10002 name=Bezalel Simmel gender=F, Employee no=10003 name=Parto Bamford gender=M, Employee no=10004 name=Chirstian Koblick gender=M, Employee no=10005 name=Kyoichi Maliniak gender=M, Employee no=10006 name=Anneke Preusig gender=F, Employee no=10007 name=Tzvetan Zielinski gender=F, Employee no=10008 name=Saniya Kalloufi gender=M, Employee no=10009 name=Sumant Peac gender=F, Employee no=10010 name=Duangkaew Piveteau gender=F, Employee no=10011 name=Mary Sluis gender=F, Employee no=10012 name=Patricio Bridgland gender=M, Employee no=10013 name=Eberhardt Terkki gender=M, Employee no=10014 name=Berni Genin gender=M, Employee no=10015 name=Guoxiang Nooteboom gender=M, Employee no=10016 name=Kazuhito Cappelletti gender=M, Employee no=10017 name=Cristinel Bouloucos gender=F, Employee no=10018 name=Kazuhide Peha gender=F, Employee no=10019 name=Lillian Haddadi gender=M, Employee no=10020 name=Mayuko Warwick gender=M]
2019-09-25 21:48:48,886 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
LIMIT %(param_1)s
2019-09-25 21:48:48,888 INFO sqlalchemy.engine.base.Engine {'param_1': 1}
Employee no=10001 name=Georgi Facello gender=M
+++++++++++++++++++++++++++++
2019-09-25 21:48:48,894 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees
LIMIT %(param_1)s
2019-09-25 21:48:48,896 INFO sqlalchemy.engine.base.Engine {'param_1': 1}
Employee no=10001 name=Georgi Facello gender=M
first方法本质上就是limit语句
聚合、分组
from sqlalchemy
import func
query
= session
.query
(func
.count
(Employee
.emp_no
))
print(query
.all())
print(query
.first
())
print(query
.one
())
print(query
.scalar
())
print(session
.query
(func
.max(Employee
.emp_no
)).scalar
())
print(session
.query
(func
.min(Employee
.emp_no
)).scalar
())
print(session
.query
(func
.avg
(Employee
.emp_no
)).scalar
())
query
= session
.query
(Employee
.gender
, func
.count
(Employee
.emp_no
)).group_by
(Employee
.gender
).all()
for g
,y
in query
:
print(g
.value
, y
)
2019-09-25 22:04:41,623 INFO sqlalchemy.engine.base.Engine SELECT count(employees.emp_no) AS count_1
FROM employees
2019-09-25 22:04:41,624 INFO sqlalchemy.engine.base.Engine {}
[(20,)]
2019-09-25 22:04:41,629 INFO sqlalchemy.engine.base.Engine SELECT count(employees.emp_no) AS count_1
FROM employees
LIMIT %(param_1)s
2019-09-25 22:04:41,631 INFO sqlalchemy.engine.base.Engine {'param_1': 1}
(20,)
2019-09-25 22:04:41,635 INFO sqlalchemy.engine.base.Engine SELECT count(employees.emp_no) AS count_1
FROM employees
2019-09-25 22:04:41,637 INFO sqlalchemy.engine.base.Engine {}
(20,)
2019-09-25 22:04:41,640 INFO sqlalchemy.engine.base.Engine SELECT count(employees.emp_no) AS count_1
FROM employees
2019-09-25 22:04:41,642 INFO sqlalchemy.engine.base.Engine {}
20
2019-09-25 22:04:41,646 INFO sqlalchemy.engine.base.Engine SELECT max(employees.emp_no) AS max_1
FROM employees
2019-09-25 22:04:41,648 INFO sqlalchemy.engine.base.Engine {}
10020
2019-09-25 22:04:41,653 INFO sqlalchemy.engine.base.Engine SELECT min(employees.emp_no) AS min_1
FROM employees
2019-09-25 22:04:41,654 INFO sqlalchemy.engine.base.Engine {}
10001
2019-09-25 22:04:41,658 INFO sqlalchemy.engine.base.Engine SELECT avg(employees.emp_no) AS avg_1
FROM employees
2019-09-25 22:04:41,659 INFO sqlalchemy.engine.base.Engine {}
10010.5000
2019-09-25 22:04:41,664 INFO sqlalchemy.engine.base.Engine SELECT employees.gender AS employees_gender, count(employees.emp_no) AS count_1
FROM employees GROUP BY employees.gender
2019-09-25 22:04:41,666 INFO sqlalchemy.engine.base.Engine {}
[(<MyEnum.M: 'M'>, 12), (<MyEnum.F: 'F'>, 8)]
M 12
F 8
关联查询
class Department(Base
):
__tablename__
= 'departments'
dept_no
= Column
(String
(4), primary_key
=True)
dept_name
= Column
(String
(40), nullable
=False, unique
=True)
def __rept__(self
):
return "{} no={} name={}".format(type(self
).__name__
, self
.dept_no
, self
.dept_name
)
class Dept_emp(Base
):
__tablename__
= 'dept_emp'
emp_no
= Column
(Integer
, ForeignKey
('employees.emp_no', ondelete
='CASCADE'),primary_key
=True)
dept_no
= Column
(String
(4), ForeignKey
('departments.dept_no', ondelete
='CASCADE'),primary_key
=True)
from_date
= Column
(Date
, nullable
=False)
to_date
= Column
(Date
, nullable
=False)
def __repr__(self
):
return "{} empno={} deptno={}".format(type(self
).__name__
, self
.emp_no
, self
.dept_no
)
隐式内连接
results
= session
.query
(Employee
, Dept_emp
).filter(Employee
.emp_no
== Dept_emp
.emp_no
).filter(Employee
.emp_no
== 10010).all()
show
(results
)
2019-09-25 23:07:05,946 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date, dept_emp.emp_no AS dept_emp_emp_no, dept_emp.dept_no AS dept_emp_dept_no, dept_emp.from_date AS dept_emp_from_date, dept_emp.to_date AS dept_emp_to_date
FROM employees, dept_emp
WHERE employees.emp_no = dept_emp.emp_no AND employees.emp_no = %(emp_no_1)s
2019-09-25 23:07:05,948 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
(Employee no=10010 name=Duangkaew Piveteau gender=F, Dept_emp empno=10010 deptno=d004)
(Employee no=10010 name=Duangkaew Piveteau gender=F, Dept_emp empno=10010 deptno=d006)
=============================
使用join
results
= session
.query
(Employee
).join
(Dept_emp
).filter(Employee
.emp_no
== 10010).all()
results
= session
.query
(Employee
).join
(Dept_emp
, Employee
.emp_no
== Dept_emp
.emp_no
).filter(Employee
.emp_no
== 10010).all()
print(results
)
2019-09-25 23:14:22,154 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees INNER JOIN dept_emp ON employees.emp_no = dept_emp.emp_no
WHERE employees.emp_no = %(emp_no_1)s
2019-09-25 23:14:22,156 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
2019-09-25 23:14:22,162 INFO sqlalchemy.engine.base.Engine SELECT employees.emp_no AS employees_emp_no, employees.birth_date AS employees_birth_date, employees.first_name AS employees_first_name, employees.last_name AS employees_last_name, employees.gender AS employees_gender, employees.hire_date AS employees_hire_date
FROM employees INNER JOIN dept_emp ON employees.emp_no = dept_emp.emp_no
WHERE employees.emp_no = %(emp_no_1)s
2019-09-25 23:14:22,164 INFO sqlalchemy.engine.base.Engine {'emp_no_1': 10010}
[Employee no=10010 name=Duangkaew Piveteau gender=F]
这两种写法,返回都只有一行数据。原因在于query(Employee)这个只能返回一个实体对象中去,为了解决这个问题,需要修改实体类Employee,增加属性用来存放部门信息。
sqlalchemy.orm.relationship(实体类名字符串)
class Employee(Base
):
__tablename__
= 'employees'
emp_no
= Column
(Integer
, primary_key
=True)
birth_date
= Column
(Date
, nullable
=False)
first_name
= Column
(String
(14), nullable
=False)
last_name
= Column
(String
(16), nullable
=False)
gender
= Column
(Enum
(MyEnum
), nullable
=False)
hire_date
= Column
(Date
, nullable
=False)
departments
= relationship
('Dept_emp')
def __repr__(self
):
return "{} no={} name={} {} gender={}".format(self
.__class__
.__name__
, self
.emp_no
, self
.first_name
, self
.last_name
,self
.gender
.value
)
查询信息
results
= session
.query
(Employee
).join
(Dept_emp
).filter(Employee
.emp_no
== Dept_emp
.emp_no
).filter(Employee
.emp_no
== 10010)
results
= session
.query
(Employee
).join
(Dept_emp
, Employee
.emp_no
== Dept_emp
.emp_no
),filter(Employee
.emp_no
== 10010)
results
= session
.query
(Employee
).join
(Dept_emp
, (Employee
.emp_no
== Dept_emp
.emp_no
) & (Employee
.emp_no
== 10010))
show
(results
.all())
第一种方法join(Dept_emp)中没有等值条件,会自动生成一个等值条件,如果后面有filter,filter中的条件会在where中出现。这种自动增加等值条件的方法不好。
第二种方法在join中增加等值条件,阻止了自动的等值条件的生成。推荐这种方式
第三种方法就是第二种,这种方法也可以。
只要不访问departments属性,就不会查dept_emp这张表。
总结
在开发中,一般都会采用ORM框架,这样就可以使用对象操作表了。 定义表映射的类,使用Column的描述器定义类的属性,使用ForeignKey来定义外键约束。 如果在一个对象中,想查看其它表对应的对象内容,就要使用relationship来定义关系。
是否使用外键约束?
力挺派 能使数据保证完整性、一致性弃用派 开发难度增加,大量数据的时候影响插入、修改、删除的效率。
在业务层保证数据的一致性。