如何在SQLAlchemy中为Oracle更新查询移动CTE

时间:2019-05-09 14:11:58

标签: python database oracle sqlalchemy

我正面临由sqlalchemy生成的查询的oracle错误ORA-00928: missing SELECT keyword。该问题已得到描述,并已here得到了解决。

我的查询如下:

WITH table2 (id) AS (
    SELECT id
    FROM table3
)

UPDATE table SET id=1 
WHERE EXISTS (
    SELECT * 
    FROM table 
    WHERE id IN (SELECT id FROM table2)
)

并由此生成:

table2 = session.query(table3.id).cte()
update(table).where(exists().where(table.id.in_(table2))).values(id=1)

现在,我想知道如何告诉sqlachemy将CTE放在WHERE子句中,而不放在UPDATE之上。

UPDATE table SET id=1 
WHERE EXISTS (
    WITH table2 (id) AS (
        SELECT id
        FROM table3
    )

    SELECT * 
    FROM table 
    WHERE id IN (SELECT id FROM table2)
)

1 个答案:

答案 0 :(得分:0)

CTE是一种从查询中提取内联视图的好方法,这样做可以使您的代码更易于阅读和维护。

当尚未发明CTE时,我们使用了内联视图。以下是一些示例(基于Scott的模式)来说明我的意思。

首先是CTE:

SQL> with tab as
  2    (select deptno from dept
  3     where deptno > 10
  4    )
  5  select e.deptno, count(*)
  6  from emp e join tab t on t.deptno = e.deptno
  7  group by e.deptno;

    DEPTNO   COUNT(*)
---------- ----------
        30          6
        20          5

可以将其移入内联视图:

SQL> select e.deptno, count(*)
  2  from emp e join (select deptno from dept
  3                   where deptno > 10
  4                  ) t on t.deptno = e.deptno
  5  group by e.deptno;

    DEPTNO   COUNT(*)
---------- ----------
        30          6
        20          5

或者,使用 old 语法,其中表(在FROM子句中用逗号分隔,联接在WHERE子句中完成(这看起来很熟悉) ):

SQL> select e.deptno, count(*)
  2  from emp e,
  3      (select deptno from dept
  4       where deptno > 10
  5      ) t
  6  where t.deptno = e.deptno
  7  group by e.deptno;

    DEPTNO   COUNT(*)
---------- ----------
        30          6
        20          5

这意味着您的查询可能看起来像这样;请注意显示您的CTE职位的评论:

update table set
  id = 1
  where exists (select *
                from table
                where id in (select id 
                             from 
                               (select id from table3)  --> this line is your CTE
                            )
               );