如何使用 SQLAlchemy 创建 SQL 视图?
回答问题 是否有“Pythonic”方式(我的意思是,没有“纯 SQL”查询)用 SQLAlchemy 定义 SQL 视图? Answers 更新: SQLAlchemy 现在有一个很棒的用法配方这里关于这个主题,我推荐。它涵盖了最新的不同 SQL Alchemy 版本并具有 ORM 集成(请参阅此答案下方的评论和其他答案)。如果您查看版本历史,您还可以了解为什么使用literal_binds是不
·
回答问题
是否有“Pythonic”方式(我的意思是,没有“纯 SQL”查询)用 SQLAlchemy 定义 SQL 视图?
Answers
更新: SQLAlchemy 现在有一个很棒的用法配方这里关于这个主题,我推荐。它涵盖了最新的不同 SQL Alchemy 版本并具有 ORM 集成(请参阅此答案下方的评论和其他答案)。如果您查看版本历史,您还可以了解为什么使用literal_binds
是不确定的(简而言之:绑定参数应该留给数据库),但仍然可以说任何其他解决方案都会让大多数用户不满意。我留下以下答案主要是出于历史原因。
原始答案: 据我所知,开箱即用不支持创建(只读非物化)视图。但是在 SQLAlchemy 0.7 中添加这个功能很简单(类似于我在这里给出的示例)。你只需要编写一个编译器扩展CreateView
。有了这个扩展,你就可以写了(假设t
是一个表对象,列id
)
createview = CreateView('viewname', t.select().where(t.c.id>5))
engine.execute(createview)
v = Table('viewname', metadata, autoload=True)
for r in engine.execute(v.select()):
print r
这是一个工作示例:
from sqlalchemy import Table
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Executable, ClauseElement
class CreateView(Executable, ClauseElement):
def __init__(self, name, select):
self.name = name
self.select = select
@compiles(CreateView)
def visit_create_view(element, compiler, **kw):
return "CREATE VIEW %s AS %s" % (
element.name,
compiler.process(element.select, literal_binds=True)
)
# test data
from sqlalchemy import MetaData, Column, Integer
from sqlalchemy.engine import create_engine
engine = create_engine('sqlite://')
metadata = MetaData(engine)
t = Table('t',
metadata,
Column('id', Integer, primary_key=True),
Column('number', Integer))
t.create()
engine.execute(t.insert().values(id=1, number=3))
engine.execute(t.insert().values(id=9, number=-3))
# create view
createview = CreateView('viewname', t.select().where(t.c.id>5))
engine.execute(createview)
# reflect view and print result
v = Table('viewname', metadata, autoload=True)
for r in engine.execute(v.select()):
print r
如果你愿意,你也可以专门研究一种方言,例如
@compiles(CreateView, 'sqlite')
def visit_create_view(element, compiler, **kw):
return "CREATE VIEW IF NOT EXISTS %s AS %s" % (
element.name,
compiler.process(element.select, literal_binds=True)
)
更多推荐
所有评论(0)