如何使用SQLAlchemy创建SQL视图?

发布于 2021-01-29 19:37:00

是否有“ Pythonic”方式(我的意思是,没有“ pure SQL”查询)来使用SQLAlchemy定义SQL视图?

关注者
0
被浏览
672
1 个回答
  • 面试哥
    面试哥 2021-01-30
    为面试而生,有面试问题,就找面试哥。

    更新:
    又见SQLAlchemy的使用配方这里

    据我所知,开箱即用不支持创建(只读非实例化)视图。但是在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)
             )
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看