在 Python 中执行原始 SQL 查询时出现问题:sqlalchemy.exc.programmingerror 处或附近出现语法错误

Problem executing raw SQL query in Python: sqlalchemy.exc.programmingerror syntax error at or near

我在 python 脚本中有一个查询,它在创建一些表后创建实体化视图。

脚本是这样的:

    from sqlalchemy import create_engine, text

    sql = '''CREATE MATERIALIZED VIEW schema1.view1 AS 
            SELECT t1.a,
              t1.b,
              t1.c,
              t2.x AS d
            FROM schema1.t1 t1
            LEFT JOIN schema1.t2 t2 ON t1.f = t2.f
            UNION ALL
            SELECT t3.a, 
              t3.b, 
              t3.c, 
              t3.d
            FROM schema1.t3 t3;'''

    con=create_engine(db_conn)

    con.execute(sql)

当我直接在数据库上运行查询成功执行。

但是当 运行在 python 中调用脚本时,我得到一个错误:

sqlalchemy.exc.ProgrammingError: (psycopg2.errors.SyntaxError) syntax error at or near "CREATE MATERIALIZED VIEW schema"

我一辈子都弄不明白它有什么问题 - 有什么想法吗?

我不知道 SQLAlchemy 是否支持 MView-Creation,但它是否应该类似或使用特定的元数据功能完成 (https://docs.sqlalchemy.org/en/13/core/schema.html)。

文本函数是为独立于数据库的 DML 而不是 DDL 而设计的。也许它适用于 DDL(我不知道 SQLAlchemy),但从设计上讲,语法不同于您直接在数据库上执行时的语法,因为 SQLAlchemy 将从用户那里抽象出数据库的详细信息.

如果 SQLAlchemy 没有为此提供一些方便的方法并且您仍然有充分的理由使用 SQLAlchemy,您可以只执行普通的 SQL Statememt数据库后端理解的方言,所以只需省略 SQL 语句的 sqlalchemies text 函数,例如:

   from sqlalchemy import create_engine, text

    sql = '''CREATE MATERIALIZED VIEW schema.view1 AS 
            SELECT t1.a,
              t1.b,
              t1.c
              t2.x AS d
            FROM schema.t1 t1
            LEFT JOIN schema.t2 t2 ON t1.f = t2.f
            UNION ALL
            SELECT t3.a, 
              t3.b, 
              t3.c, 
              t3.d
            FROM schema.t3 t3;'''

    con=create_engine(db_conn)
    con.raw_connection().cursor().execute(sql)

(但当然你必须注意后端类型然后反对 SQLAlchemy 包装语句。)


我直接使用 psycopg2 在我的 pg 服务器上测试没有任何问题。

postgres=# create schema schema;
CREATE TABLE
postgres=# create table schema.t1 (a varchar, b varchar, c varchar, f integer);
CREATE TABLE
postgres=# create table schema.t2 (x varchar, f integer);
CREATE TABLE
postgres=# create table schema.t3 (a varchar, b varchar, c varchar, d varchar);
CREATE TABLE
postgres=# commit;

使用以下脚本:

#!/usr/bin/python3
import psycopg2;

conn = psycopg2.connect("dbname=postgres")
cur = conn.cursor()
cur.execute("""
            CREATE MATERIALIZED VIEW schema.view1 AS
            SELECT t1.a,
              t1.b,
              t1.c,
              t2.x AS d
            FROM schema.t1 t1
            LEFT JOIN schema.t2 t2 ON t1.f = t2.f
            UNION ALL
            SELECT t3.a,
              t3.b,
              t3.c,
              t3.d
            FROM schema.t3 t3;
""")
conn.commit()
cur.close()
conn.close()

我测试了当前版本的 python3.7/2.7 和当前版本的 psycopg2 模块和当前库(我有 11.5 pg 客户端和 2.8.3 psycopg2)来自安装在最近 linux?你能像我一样尝试直接在 psycopg2 上执行吗?

您是否还确定您的点是普通的 ascii 点,因为语句中的所有其他字符在这种情况下都是? (另请记住,unicode 中可能存在可能导致此类问题的不可见代码点。)如果您使用 Python,也许您可​​以将字符串转换为 ASCII 二进制文件并返回到 Unicode-String。如果它没有在 .encode('ASCII') 上引发错误,它应该是干净的。

这是最奇怪的事情。我已经将我的查询文本从我用来在我的 pg 数据库中导航的另一个工具复制到 VS 代码中。 @EOhm 回答的最后一部分让我想到了在 VS Code 中输入整个内容而不是 copy/pasting。

一切正常。

即使粘贴的文本和我键入的内容在各个方面都完全相同。很明显,有一些不可见的格式导致了这个问题。