Mat*_*sen 5 python oracle sqlalchemy oracle12c
我正在尝试在 SQLAlchemy 中为 Oracle 12CR1 数据库生成以下人为的 DML 语句:
INSERT INTO baz(名称,数量)
带条 AS (
选择 bar.name, bar.qty
发件人栏
)
选择 foo.name, bar.qty
FROM foo JOIN bar ON foo.name = bar.name
但是,SQLAlchemy 似乎乱序生成,如下所示:
带条 AS (
选择 bar.name, bar.qty
发件人栏
)
INSERT INTO baz(名称,数量)
选择 foo.name, bar.qty
FROM foo JOIN bar ON foo.name = bar.name
无序执行此操作失败并显示ORA-00923: FROM keyword not found where expected.
我的理论是,SQLAlchemy 假设 PostgreSQL 语法是WITH ... INSERT INTO ... SELECT ...并且不尊重 Oracle 语法,即INSERT INTO ... WITH ... SELECT ....
有没有办法让它与 Oracle 一起工作,或者至少有一种方法可以修改 aninsert().from_select()的编译方式?
重现:
from sqlalchemy import (Table, Column, String, Integer,
MetaData, select, func)
from sqlalchemy.dialects import oracle
metadata = MetaData()
foo = Table('foo', metadata, Column('name', String))
bar = Table('bar', metadata, Column('name', String), Column('qty', Integer))
baz = Table('baz', metadata, Column('name', String), Column('qty', Integer))
with_bar = select([bar.c.name, bar.c.qty]).cte('bar')
sel = select([foo.c.name, with_bar.c.qty])
sel = sel.select_from(
foo.join(with_bar,
foo.c.name == with_bar.c.name
)
)
ins = baz.insert().from_select([baz.c.name, baz.c.qty], sel)
print ins.compile(dialect=oracle.dialect())
Run Code Online (Sandbox Code Playgroud)
小智 1
您将需要对语句进行自定义呈现。这是帮助我在另一种方言上解决这个确切问题的代码(我已将其更改为 oracle)
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import ClauseElement, Executable
class InsertFromSelect(Executable, ClauseElement):
def __init__(self, table, select):
self.table = table
self.select = select
@compiles(InsertFromSelect, "oracle")
def visit_insert_from_select(element, compiler, **kw):
return "INSERT INTO %s (%s)" % (
compiler.process(element.table, asfrom=True, **kw),
compiler.process(element.select, **kw)
)
#target table to insert
table = sqlalchemy.Table('foo' MetaData=())
#statement with a CTE / WITH clause
baz = select().select_from(sqlalchemy.text('select * from bar').columns().cte())
#print or run the new statement, correctly ordered
print(
InsertFromSelect(table,baz)
)
Run Code Online (Sandbox Code Playgroud)
本质上,您将创建一个新元素InsertFromSelect来分别保存查询和插入,然后创建一个编译访问器将它们呈现在正确的位置。
| 归档时间: |
|
| 查看次数: |
1215 次 |
| 最近记录: |