【问题标题】:SQLAlchemy Create View in PostgresQLSQLAlchemy 在 PostgresQL 中创建视图
【发布时间】:2019-10-16 17:39:47
【问题描述】:

我正在尝试使用 SQLAlchemy 创建一个视图,并将 Postgresql 作为基础数据库。用于创建视图的单独选择查询运行良好并返回结果,但是当我在创建视图中使用它时,我收到错误 sqlalchemy.exc.NoSuchTableError: Popular,这意味着未选择视图。当我尝试从视图中选择时出现错误。创建视图不会引发任何错误,但不会创建视图。这是我的代码:

from sqlalchemy import *
import sqlalchemy as db
from sqlalchemy import func
from sqlalchemy import desc
from sqlalchemy import Table
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import Executable, ClauseElement

try:
    engine = db.create_engine('postgresql://user:pass@localhost:5432/db_name')
    connection = engine.connect()

except:
    print('Error establishing DB connection')

# Import metadata
metadata = db.MetaData()

# Import articles, authors and log tables
art = db.Table('articles', metadata, autoload=True, autoload_with=engine)
aut = db.Table('authors', metadata, autoload=True, autoload_with=engine)
log = db.Table('log', metadata, autoload=True, autoload_with=engine)


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)
         )



# Method to create view with top three articles
def view_top_three():
    top_three_view = CreateView('popular', db.select([art.columns.title, func.count(log.columns.path)]) \
        .where(func.concat('/article/', art.columns.slug) == log.columns.path) \
        .where(log.columns.path != "/") \
        .group_by(log.columns.path, art.columns.title) \
        .order_by(desc(func.count(log.columns.path))) \
        .limit(3))

    engine.execute(top_three_view)
    v = Table('popular', metadata, autoload=True, autoload_with=engine)
    for r in engine.execute(v.select()):
        print(r)


# Call the method which creates view and selects from view
view_top_three()

任何帮助将不胜感激。

【问题讨论】:

  • 非常感谢@IljaEverilä 将我指向该帖子。问题是自动提交。创建引擎时添加 .execution_options(autocommit=True) 解决了我的问题
  • 虽然这可能不是最好的解决方案,因为现在每个语句在没有显式事务的情况下运行都会隐式提交。如果您选择这条路线,最好在语句上发出所需的选项以自行执行:engine.execute(top_three_view.execution_options(...)),但由于 CREATE VIEW 是 DDL,因此您的类无论如何都应该继承自 DDLElement。跨度>

标签: python postgresql sqlalchemy


【解决方案1】:

由于您的CreateView 继承自ExecutableClauseElement,因此它不被视为数据更改操作。换句话说

engine.execute(top_three_view)

执行CREATE VIEW 语句,然后在连接返回池时隐式回滚。

相反,它应该是DDLElement 的子类,如usage recipes wiki 所示。只需更改基类即可让SQLAlchemy autocommit 正常工作。

【讨论】:

    【解决方案2】:

    我找到了解决方案。问题与自动提交有关。在创建引擎时将 autocommit 设置为 true 解决了如下问题:

    engine = db.create_engine('postgresql://user:pass@localhost:5432/db_name').execution_options(autocommit=True)
    

    特别提到@ilja-everilä

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 2015-05-04
      • 2021-08-05
      • 2022-01-15
      • 1970-01-01
      • 2012-04-03
      • 1970-01-01
      • 2015-06-13
      相关资源
      最近更新 更多