使用SQLAlchemy

时间:2017-10-31 00:57:46

标签: python sqlalchemy

我真的想要理解SQLAlchemy,但它的进展缓慢而令人困惑。我有以下查询:

INSERT INTO
    user (name, email)
SELECT
    :name, :email
WHERE NOT EXISTS (
    SELECT * FROM other WHERE other.id > :some_id
)
RETURNING id

我希望通过SQLAlchemy以更加pythonic的方式运行它,而不仅仅是提供原始SQL来执行。

我无法确定哪些功能存在于哪些对象 - filterwhereinsertadd ...文档非常详细压倒性的,我迷路了。

我已经生成了user个生成的对象并等待添加到数据库中 - 这是应该这样做的查询,如果有人可以帮我弄清楚如何构建它。

我希望所有人都在一个查询中,因为存在竞争条件,有时我会得到一个新的other对象,这会使当前user个对象无效,所以我没有更长的时间想要添加它们。

1 个答案:

答案 0 :(得分:1)

我设法使用SQLAlchemy-Core呈现您的查询。我将提供简单Table对象和使用declarative_base的模型的示例。

鉴于这个演示代码:

from sqlalchemy import table, column, Unicode, String, Integer

user = table(
    'user',
    column('id', Integer),
    column('name', Unicode),
    column('email', String),
)

other = table(
    'other',
    column('id', Integer),
    column('name', Unicode),
    column('email', String),
)

如果您使用ORM,那么您的定义可能如下所示:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, Unicode, String


Base = declarative_base()

class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    name = Column('name', Unicode)
    email = Column('email', String)


class Other(Base):
    __tablename__ = 'other'

    id = Column(Integer, primary_key=True)
    name = Column('name', Unicode)
    email = Column('email', String)

# Pull out the `Table` objects from the mapped models.
user = User.__table__
other = Other.__table__

鉴于此,您可以像这样呈现查询:

from sqlalchemy import select, literal, exists, text

# Your inputs.
name = 'foo'
email = 'foo@example.com'
other_id = 1

# Compile the query for demonstration purposes
print(
    user
    .insert()
    .from_select(
        ['name', 'email'],
        select(
            [literal(name),
             literal(email)])
        .where(~exists([other.c.id])
               .where(other.c.id > other_id))
    )
    .returning(text('id'))
)

编译查询将为您提供以下SQL字符串:

INSERT INTO "user" (name, email) SELECT :param_1 AS anon_1, :param_2 AS anon_2 
WHERE NOT (EXISTS (SELECT other.id 
FROM other 
WHERE other.id > :id_1)) RETURNING id