回答问题

是否有“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)
         )
Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐