Python 使用 Pandas 导入 .csv to_sql 的脚本失败,除非我 DROP TRIGGER 更新物化视图

Python script for importing .csv to_sql with Pandas fails unless I DROP TRIGGER for updating materialized view

我有一个带有 table 的 Postgres 数据库,它有一个物化视图,每次通过以下用户定义的函数和触发器对 table 进行更改时,该视图都会自动更新:

create function refresh_matview_dohscrapemat()
returns trigger language plpgsql
as $$
begin
    refresh materialized view dohscrape;
    return null;
end $$;
create trigger refresh_matview_dohscrapemat
after insert or update or delete or truncate
on dohscrape for each statement
execute procedure refresh_matview_dohscrapemat();

我有一个 python 脚本,它使用 pandas 自动将 .csv 文件导入到这个 table 中,只有当我删除 TRIGGER 以更新运行 之前的物化视图。

如果我尝试 运行 脚本而不删除触发器,我会收到以下错误:

sqlalchemy.exc.NotSupportedError: (psycopg2.NotSupportedError) "dohscrape" is not a materialized view CONTEXT: SQL statement "refresh materialized view dohscrape" PL/pgSQL function refresh_matview_dohscrapemat() line 3 at SQL statement [SQL: 'INSERT INTO dohscrape (filename, content) VALUES (%(filename)s, %(content)s)'] [parameters: ({'filename':...(Background on this error at: http://sqlalche.me/e/tw8g)

它说 "dohscrape" 不是物化视图,这是正确的,因为那是 table 的名称,而不是物化视图。实例化视图命名为 "dohscrapemat".

错误消息中的link指向以下信息:

NotSupportedError Exception raised in case a method or database API was used which is not supported by the database, e.g. requesting a .rollback() on a connection that does not support transaction or has transactions turned off.

This error is a DBAPI Error and originates from the database driver (DBAPI), not SQLAlchemy itself.

但我不明白这与导致 by/related 触发更新物化视图的错误有何关系,我认为这是根本问题,因为删除它可以解决错误。

一旦我让脚本上传到 table 并重新创建触发器,一切正常,但我希望能够 运行 这个脚本而不必删除并重新创建触发器。

为什么刷新实体化视图的触发器导致导入错误?为什么 pandas/sqlalchemy/psycopg2 将我的 table 与其物化视图混淆了?

上传到数据库的 python 脚本中的代码片段是:

for files in source:
    if files.endswith(".csv"):
        df = pd.read_csv(os.path.join(sourcepath,files))
        df.to_sql(name='dohscrape',con=dbconn,if_exists='append',index=False)

我正在使用 Python 3.7 和 Postgres 11。

It says "dohscrape" is not a materialized view, which is correct because that's the name of the table not the materialized view. The materialized view is named "dohscrapemat".

所以你的触发函数显然是错误的。替换

    refresh materialized view dohscrape; -- error

    refresh materialized view dohscrapemat;