Python 在SQLAlchemy中,如何查询复合主键?

Python 在SQLAlchemy中,如何查询复合主键?,python,sql,sqlalchemy,compound-key,Python,Sql,Sqlalchemy,Compound Key,我使用SQLAlchemy以编程方式使用复合外键查询表。e、 g: CREATE TABLE example ( id INT NOT NULL, date TIMESTAMP NOT NULL, data VARCHAR(128) PRIMARY KEY (id, date) ) 我想获取一个值列表并返回行,例如: interesting_data = ( (1, '2016-5-1'), (1, '2016-6-1'), (2, '2016-6-1'),

我使用SQLAlchemy以编程方式使用复合外键查询表。e、 g:

CREATE TABLE example (
id INT NOT NULL,
date TIMESTAMP NOT NULL,
data VARCHAR(128)
PRIMARY KEY (id, date)
)
我想获取一个值列表并返回行,例如:

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)
如果每一列都是独立的,我就能做到

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)
)

但这显然无法带来唯一的匹配(id、日期)元组。我怀疑有一种方法可以指定要查询的复合主键,但搜索后我找不到任何文档。

在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))
然而,我注意到的另一个问题是,您将日期列与字符串数据类型进行比较。
有趣的\u数据
列表应该是

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)),
)
另外,请注意,可以创建一个基本语句,然后递增地向其中添加子句,从而(希望)提高可读性和代码重用性

因此,可以将上述内容写成

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)
这将生成以下sql(我添加的新行和空格):


注意:如果您有很多行需要像这样进行筛选,那么创建一个临时表,从
有趣的\u数据
将行插入这个临时表,然后内部联接到这个表,可能会更有效,而不是像上面所示添加where子句。

假设您的模型类被称为
示例
,其中(id,date)是复合主键:

您可以使用以下选项之一进行查询:

import sqlalchemy
...
Example.query.get((id, date))

import sqlalchemy
...
Example.query.get((id, date))
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))