用Elixir执行SQL查询

5 投票
5 回答
4050 浏览
提问于 2025-04-15 16:50

我在一个项目中使用Elixir,连接到一个Postgres数据库。我想在这个数据库上运行以下查询,但由于我对Elixir和SQLAlchemy还不太熟悉,不知道该怎么做。有人知道吗?

VACUUM FULL ANALYZE table

更新

我遇到的错误是:“UnboundExecutionError: 找不到配置在SQL表达式或这个会话上的绑定”。即使在之前调用了session.close(),结果也是一样。我尝试使用metadata.bind.execute(),这在简单的选择查询中是有效的。但是对于VACUUM,它提示 - “InternalError: (InternalError) VACUUM不能在事务块内运行”,所以现在我在想怎么把这个关闭。

更新 2

我可以让查询执行,但即使我创建了一个新会话并关闭了之前的会话,仍然会出现同样的错误。

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# ... insert stuff
old_session.commit()
old_session.close()

new_sess = sessionmaker(autocommit=True)
new_sess.configure(bind=create_engine('postgres://user:pw@host/db', echo=True))
sess = new_sess()
sess.execute('VACUUM FULL ANALYZE table')
sess.close()

我得到的输出是

2009-12-10 10:00:16,769 INFO sqlalchemy.engine.base.Engine.0x...05ac VACUUM FULL ANALYZE table
2009-12-10 10:00:16,770 INFO sqlalchemy.engine.base.Engine.0x...05ac {}
2009-12-10 10:00:16,770 INFO sqlalchemy.engine.base.Engine.0x...05ac ROLLBACK
finishing failed run, (InternalError) VACUUM cannot run inside a transaction block
 'VACUUM FULL ANALYZE table' {}

更新 3

感谢所有回复的人。 我没有找到我想要的解决方案,但我想我会采用这里描述的方案 PostgreSQL - 如何在代码中从事务块外运行VACUUM?。这不是最理想的,但它有效。

5 个回答

1

UnboundExecutionError 的意思是你的会话没有和一个引擎绑定在一起,因此无法从传给 execute() 的查询中找到引擎。你可以直接使用 engine.execute(),或者在调用 session.execute() 时,传入额外的 mapper 参数(这个参数可以是和查询中使用的表对应的映射器或者映射模型),这样 SQLAlchemy 就能找到合适的引擎了。

InternalError 表示你正在尝试在一个明确开始的事务中执行这个语句(是用 BEGIN 语句开始的)。在这之前你有没有执行过其他语句而没有调用 commit()?如果有的话,记得在执行 VACUUM 之前调用 commit()rollback() 方法来结束事务。另外,sessionmaker() 有几个参数可以告诉 SQLAlchemy 什么时候应该开始事务。

2

你需要把会话绑定到一个引擎上

session.bind = metadata.bind
session.execute('YOUR SQL STATEMENT')
10

真是的,我知道答案就在我眼前。如果你像我一样设置了连接的话。

metadata.bind = 'postgres://user:pw@host/db'

解决这个问题其实很简单,

conn = metadata.bind.engine.connect()

old_lvl = conn.connection.isolation_level
conn.connection.set_isolation_level(0)
conn.execute('vacuum analyze table')
conn.connection.set_isolation_level(old_lvl)

这和这里提到的内容很相似,PostgreSQL - 如何在事务块外从代码中运行VACUUM?,因为在背后,sqlalchemy是通过psycopg来连接Postgres的。Connection.connection实际上是psycopg连接的一个代理。一旦我意识到这一点,这个问题就浮现在我的脑海中,我决定再试一次。

希望这能帮助到某个人。

撰写回答