【问题标题】:Postgres can't drop table when view is present存在视图时,Postgres 无法删除表
【发布时间】:2020-06-30 17:09:38
【问题描述】:
我正在使用to_sql() 中的if_exists='replace' 选项使用sqlalchemy 和psycopg2 从python 将数据写入postgres 表。这会删除表,然后重新创建它。但是,如果我定义了一个使用该表的视图,to_sql() 命令将失败,因为 postgres 不会删除该表。除了首先手动删除视图,重新创建它之外,还有其他方法吗?谢谢。
【问题讨论】:
标签:
python-3.x
postgresql
sqlalchemy
【解决方案1】:
如果您的目标是 DROP 包含相关对象的 TABLE,例如 VIEW,您需要使用 CASCADE 关键字来强制 DROP 相关对象(这是一个递归操作)。
详见 PostgreSQL dependencies tracking:
为保证整个数据库结构的完整性,PostgreSQL
确保您不能丢弃其他对象仍然存在的对象
取决于。
默认情况下这是不可行的,实际上在一个表上创建一个视图是防止这个表被意外删除的一种方便的方法。无论如何,您可能还想阅读此post 以使用 SQLAlchemy 实现 CASCADE 行为。
那么在重新创建表后重新创建丢失的相关对象仍然是您的责任。 SQLAlchemy 似乎没有相关视图的表示。但它有一个package to create views,可能会在一定程度上填补这个空白(未测试)。
因此,它不能由 SQLAlchemy 单独处理。您将需要一个脚本/函数来播放 DDL 语句来重新创建您的依赖项(可能使用上面提到的包)。
如果您可以使用纯 SQL 标准(或使用包)重新创建它,那么您将不会失去 SQLAlchemy ORM 的好处(至少是抽象数据库引擎并可以移植到另一个引擎的能力)。
关于依赖跟踪,查看应该重新创建哪些相关对象的简单方法是:
BEGIN;
DROP TABLE mytable CASCADE;
ROLLBACK;
你也可以使用pg_depend这个函数,非常方便,但是是PostgreSQL特有的。