ProgrammingError: (psycopg2.errors.UndefinedColumn),在使用 sqlalchemy 时

w8f*_*rw8 3 python sql postgresql sqlalchemy

我在查询在 postgres db(本地)上使用 sqlalchemy 创建的表时遇到问题。

虽然我能够执行并通过以下方式接收查询结果:

SELECT * FROM olympic_games 
Run Code Online (Sandbox Code Playgroud)

当我尝试访问单列或对表执行任何其他操作时收到错误消息:

SELECT games FROM olympic_games
Run Code Online (Sandbox Code Playgroud)

错误信息是(从波兰语翻译的几句话):

ProgrammingError: (psycopg2.errors.UndefinedColumn) B??D: 列“游戏”不存在

第 1 行:SELECT COUNT(Sport)
^
提示:也许您的意思是“olympic_games.Games”。

SQL: SELECT games FROM olympic_games LIMIT 5;]
(此错误的背景:http : //sqlalche.me/e/f405 )

它几乎总和该程序看不到,或者可以访问特定列,并显示它不存在。

我尝试使用table.column格式访问,但效果不佳。我也可以看到列名,通过information_schema.columns

数据 (.csv) 加载了pd.read_csv,然后加载了DataFrame.to_sql。代码如下,谢谢帮助!

engine = create_engine('postgresql://:@:/olympic_games')

with open('olympic_athletes_2016_14.csv', 'r') as file:
    df = pd.read_csv(file, index_col='ID')
df.to_sql(name = 'olympic_games', con = engine, if_exists = 'replace', index_label = 'ID')
Run Code Online (Sandbox Code Playgroud)

两个执行命令都返回相同的错误:

with engine.connect() as con:
    rs = con.execute("SELECT games FROM olympic_games LIMIT 5;")
    df_fetch = pd.DataFrame(rs.fetchall())
Run Code Online (Sandbox Code Playgroud)
df_fetch2 = engine.execute("""SELECT games FROM olympic_games LIMIT 5;""").fetchall()
Run Code Online (Sandbox Code Playgroud)

Par*_*ait 7

本质上,这是 PostgreSQL手册中提到的列标识符的双引号问题:

引用标识符也使其区分大小写,而未引用的名称始终折叠为小写。例如,标识符 FOO、foo 和 "foo" 被 PostgreSQL 认为是相同的,但是 "Foo" 和 "FOO" 与这三个不同并且彼此不同。

当您的任何 Pandas 数据框列包含DataFrame.to_sql大小写混合时,通过在CREATE TABLE阶段创建带有双引号的列来保持区分大小写。具体来说,使用替换时的以下 Python Pandas 代码

df.to_sql(name='olympic_games', con=engine, if_exists='replace', index_label='ID')
Run Code Online (Sandbox Code Playgroud)

如果Sport是数据框中的标题 case 列,则在 Postgres 中翻译如下:

df.to_sql(name='olympic_games', con=engine, if_exists='replace', index_label='ID')
Run Code Online (Sandbox Code Playgroud)

一旦标识符被混合大小写引用,它必须始终以这种方式引用。因此sport与 不一样"Sport"。请记住,在 SQL 中,双引号实际上与单引号不同,单引号在 Python 中可以互换。

要修复,请考虑将所有 Pandas 列渲染为小写,因为"games"games, Gamesor GAMES(但不是"Games"or "GAMES")相同。

df.columns = df.columns.str.lower()
df.to_sql(name='olympic_games', con=engine, if_exists='replace', index_label='ID')
Run Code Online (Sandbox Code Playgroud)

或者,保持原样并适当引用:

DROP TABLE IF EXISTS public."olympic_games";

CREATE TABLE public."olympic_games"
(
    ...
    "Sport" varchar(255)
    "Games" varchar(255)
    ...
);
Run Code Online (Sandbox Code Playgroud)