SQLAlchemy生成的SQL不正确

时间:2017-05-29 21:00:33

标签: python sqlalchemy

我有一个函数返回一个查询,该查询将通过给定的帐户ID获取“电子邮件的新优先级”。 首先,它为该帐户选择一个域名,然后为其选择一个数据结构。 一切都应该是好的IMO,但目前还不行:SQLAlchemy正在生成语法错误的SQL,我无法理解如何解决它。以下是样本:

def unprocessed_by_account_id(account_id: str):
    account_domain = select(
        [tables.organizations.c.organization_id]).select_from(
        tables.accounts.join(
            tables.email_addresses,
            tables.accounts.c.account_id == tables.email_addresses.c.email_address,
        ).join(tables.organizations)
    ).where(
        tables.accounts.c.account_id == account_id,
    )
    domain_with_subdomains = concat('%', account_domain)
    fields = [
        tables.users.c.first_name,

        …
        tables.priorities.c.name,
    ]
    fromclause = tables.users.join(
        …
    ).join(tables.organizations)
    whereclause = and_(
        …
        tables.organizations.c.organization_id.notlike(
            domain_with_subdomains),
    )
    stmt = select(fields).select_from(fromclause).where(whereclause)

    return stmt

print(unprocessed_by_account_id(‘foo’))

因此它会生成:

SELECT
  users.first_name,
  …
  priorities.name
FROM (SELECT organizations.organization_id AS organization_id
      FROM accounts
        JOIN email_addresses
          ON accounts.account_id = email_addresses.email_address
        JOIN organizations
          ON organizations.organization_id = email_addresses.organization_id
      WHERE accounts.account_id = :account_id_1), users
  JOIN
    …
  JOIN organizations
    ON organizations.organization_id = email_addresses.organization_id
WHERE emails.account_id = :account_id_2 AND
      priorities_new_emails.status = :status_1 AND
      organizations.organization_id NOT LIKE
      concat(:concat_1, (SELECT organizations.organization_id
                         FROM accounts
                           JOIN email_addresses ON accounts.account_id =
                                                   email_addresses.email_address
                           JOIN organizations
                             ON organizations.organization_id =
                                email_addresses.organization_id
                         WHERE accounts.account_id = :account_id_1))

但第一个

(SELECT organizations.organization_id AS organization_id
      FROM accounts
        JOIN email_addresses
          ON accounts.account_id = email_addresses.email_address
        JOIN organizations
          ON organizations.organization_id = email_addresses.organization_id
      WHERE accounts.account_id = :account_id_1)

这里多余并产生

[2017-05-29 23:49:51] [42601] ERROR: subquery in FROM must have an alias
[2017-05-29 23:49:51] Hint: For example, FROM (SELECT ...) [AS] foo.
[2017-05-29 23:49:51] Position: 245

我尝试使用account_domain = account_domain.cte(),但没有运气,除了子查询按预期转到WITH子句。 我也试过了with_only_columns而没有任何效果。 我认为Alchemy正在添加这个语句,因为它在WHERE子句中看到它,并认为如果没有它,过滤将导致错误,但我不确定。 此外,我必须提及,除了没有concat(‘%’, account_domain)notlike!=之外,该语句几乎相同。 我也尝试在这里和那里插入alias,但也没有成功。如果我手动删除select中的第一个语句是纯SQL,那么我会得到可预期的结果。

感谢任何帮助,谢谢。

1 个答案:

答案 0 :(得分:1)

如果您使用子查询作为值,则需要声明它as_scalar()

domain_with_subdomains = concat('%', account_domain.as_scalar())