SQLAlchemy:WITH new_values(id,field)as(values(...,...))

时间:2016-01-24 05:51:36

标签: python sql sqlalchemy

我正在尝试使用SQLAlchemy核心创建一个仅在DB(postgres)中命中一次的查询,如果它不存在则插入一行。

以下是查询的一部分

WITH new_values (id, field) as (
  values 
     (1, 1),
     (2, 12),
     (3, 13),
     (4, 14)
)
INSERT INTO table1 (id, field)
SELECT id, field
FROM new_values
WHERE NOT EXISTS (SELECT 1 
          FROM table1 as up 
          WHERE up.id = new_values.id);

我很困惑:

  • 如何使用指定的值创建CTE表达式(我只找到带有子查询的示例)
  • 我如何SELECT 1
  • 如何在插入中添加where?

我想使用核心API并避免直接执行。

PS: 我想在单个事务中放入的完整查询是

WITH upsert AS (
   UPDATE table2
   SET field1=field1+1
   WHERE id=1234 AND field2=42
   RETURNING *
)
INSERT INTO table2 (id, field1, field2)
SELECT 1234, 1, 42
WHERE NOT EXISTS (SELECT 1 FROM upsert);

WITH new_values (id, field) as (
  values 
     (1, 1),
     (2, 12),
     (3, 13),
     (4, 14)
)
INSERT INTO table1 (id, field)
SELECT id, field
FROM new_values
WHERE NOT EXISTS (SELECT 1 
          FROM table1 as up 
          WHERE up.id = new_values.id);

编辑: 模型

table1 = Table('table1', metadata,
    Column('id', Integer, primary_key=True),
    Column('field', Integer))

table2 = Table('table2', metadata,
    Column('id', Integer, primary_key=True),
    Column('field1', Integer),
    Column('field2', Integer))

1 个答案:

答案 0 :(得分:2)

SQLAlchemy尚未直接支持此Postgres语法。几年前实际上存在一个问题,但它有近期的历史和优先级的提高。见https://bitbucket.org/zzzeek/sqlalchemy/issues/2551/apparently-inserts-and-update-delete-can

或者,定义text()的{​​{1}}项可以columns()调用它们,所以我想了一段时间,如果将cte()转换为update,这可能会有效带有绑定参数的普通sql。但是,当CTE与with select_from相关联时,很难让SQLAlchemy正确地将insert置于查询的顶层。简而言之,在上述问题得到解决之前,我认为最好不要尝试将此方法与SQLAlchemy核心一起使用 - 使用SQL或搜索不同的upsert方法。