Dav*_*veA 5 python sql sqlalchemy compound-key
我正在使用SQLAlchemy以编程方式查询具有复合外键的表.例如:
CREATE TABLE example (
id INT NOT NULL,
date TIMESTAMP NOT NULL,
data VARCHAR(128)
PRIMARY KEY (id, date)
)
Run Code Online (Sandbox Code Playgroud)
我想获取一个值列表并获取行,例如:
interesting_data = (
(1, '2016-5-1'),
(1, '2016-6-1'),
(2, '2016-6-1'),
(3, '2016-5-1'),
(3, '2016-6-1'),
)
select(
[example.c.id, example.c.date, example.c.data],
).where(example.primary_key.in_(interesting_data)
Run Code Online (Sandbox Code Playgroud)
如果每列都是独立的,我可以做到
interesting_ids = [1,2,3]
interesting_dates = ['2016-5-1', '2016-6-1']
select(
[example.c.id, example.c.date, example.c.data],
).where(
example.c.id.in_(interesting_ids)
).where(
example.c.date.in_(interesting_dates)
)
Run Code Online (Sandbox Code Playgroud)
但这显然无法仅带来唯一匹配(id,date)元组.我怀疑有一种方法可以指定要查询的复合主键,但搜索后找不到任何文档.
在 where 子句中使用列表理解:
from sqlalchemy import and_, or_, select
stmt = select(
[example.c.id, example.c.date, example.c.data]
).where(or_(and_(example.c.id==data[0], example.c.date==data[1])
for data in interesting_data))
Run Code Online (Sandbox Code Playgroud)
但是,我注意到的一个单独问题是您正在将日期列与字符串数据类型进行比较。该interesting_data列表应该是
import datetime as dt
interesting_data = (
(1, dt.date(2016,5,1)),
(1, dt.date(2016,6,1)),
(2, dt.date(2016,6,1)),
(3, dt.date(2016,6,1)),
(3, dt.date(2016,6,1)),
)
Run Code Online (Sandbox Code Playgroud)
另请注意,可以创建一个基本语句,然后逐步向其添加子句,从而(希望)获得更好的易读性和代码重用。
所以,上面的内容可以写成
base_stmt = select([example.c.id, example.c.date, example.c.data])
wheres = or_(and_(example.c.id==data[0], example.c.date==data[1])
for data in interesting_data))
stmt = base_stmt.where(wheres)
Run Code Online (Sandbox Code Playgroud)
这会生成以下 sql(我添加的换行符和空格):
SELECT example.id, example.date, example.data
FROM example
WHERE
example.id = :id_1 AND example.date = :date_1
OR example.id = :id_2 AND example.date = :date_2
OR example.id = :id_3 AND example.date = :date_3
OR example.id = :id_4 AND example.date = :date_4
OR example.id = :id_5 AND example.date = :date_5
Run Code Online (Sandbox Code Playgroud)
注意:如果您有很多行要像这样过滤,那么创建一个临时表,从 向该临时表插入行interesting_data,然后内连接到该表可能会更有效,而不是像上面那样添加 where 子句。
假设你的模型类被调用Example, (id, date) 是复合主键:
您可以查询:
import sqlalchemy
...
Example.query.get((id, date))
Run Code Online (Sandbox Code Playgroud)
或者
import sqlalchemy
from sqlalchemy.orm import sessionmaker
...
engine = sqlalchemy.create_engine('postgresql://user:pass@localhost/db_name')
session = sessionmaker(bind=engine)()
session.query(Example).get((id, date))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2102 次 |
| 最近记录: |