SQLAlchemy:使用来自(子)查询的CTE(带有指定为文字文本的FROM子句)

Cha*_*ffy 6 python sqlalchemy

我有一个系统,用户可以按文本配置提供查询和CTE。一种可能的配置类似于以下内容:

import sqlalchemy as sa
cte = sa.select([sa.sql.text('* from foo')]).cte('foo_cte')
q = sa.select([sa.sql.text('* from (select * from foo_cte)')])
Run Code Online (Sandbox Code Playgroud)

实际上,此查询在呈现时将不包括CTE前导:

>>> print q
SELECT * from (select * from foo_cte)
Run Code Online (Sandbox Code Playgroud)

但是,如果我将所有可能的CTE添加到选择列表中:

q = q.select_from(cte)
Run Code Online (Sandbox Code Playgroud)

...然后它们在渲染时由SQLAlchemy添加了额外的和无关的FROM子句,从而使语法无效:

>>> print q
WITH foo_cte AS
(SELECT * from foo)
 SELECT * from (select * from foo_cte)
FROM foo_cte
Run Code Online (Sandbox Code Playgroud)

是否可以同时使用-打印CTE序言而不将其也添加到生成的FROM子句中?

Hal*_*Ali 5

如果您定义q

q = sa.select(['*']).select_from(cte)
Run Code Online (Sandbox Code Playgroud)

然后sqlalchemy能够找出发出正确的sql:

import sqlalchemy as sa
cte = sa.select([sa.text('* from foo')]).cte('foo_cte')    
q = sa.select(['*']).select_from(cte)

print(q)
WITH foo_cte AS
(SELECT * FROM foo)
 SELECT *
FROM foo_cte
Run Code Online (Sandbox Code Playgroud)