【问题标题】:Read table in pandas with lowercase column using sqlalchemy使用 sqlalchemy 读取带有小写列的 pandas 表
【发布时间】:2020-04-03 22:13:15
【问题描述】:

我想在我的数据库中读取一个表作为 pandas 数据框。我正在使用sqlalchemy,在我看来它只执行大写查询。

我的架构中的表 XYZ 有一个小写的列名“pred_pred”。当我执行以下操作时:

import pandas as pd
import cx_Oracle as ora
from sqlalchemy import create_engine
from sqlalchemy.engine import url

connect_url = url.URL(...)
engine = create_engine(connect_url)
connection = engine.connect()

input = pd.read_sql_query('SELECT pred_pred FROM XYZ', connection)

我收到以下错误:

DatabaseError: ORA-00904: "PRED_PRED": invalid identifier

有解决办法吗?


编辑:目前,作为一种解决方法,我只是使用* 导入所有列,然后在pandas 中处理它们,因为该表只有少数列。我仍然想知道是否有可能以更直接的方式解决这个问题。

【问题讨论】:

  • 不带引号的标识符在 SQL 中是不区分大小写的,如果我没记错的话,Oracle 会将不带引号的标识符转换为大写(例如 Postgres 正好相反)。如果您的列是小写的,也许您必须使用带引号的标识符:"pred_pred",
  • 感谢您的回复。您的意思是使用 query = 'SELECT '+"pred_pred"+' FROM XYZ' 吗?我收到相同的错误消息。
  • 不,他的意思是直接query = 'SELECT "pred_pred" FROM XYZ'。顺便说一句,永远不要使用这样的字符串连接,因为容易注入。
  • @BarbarosÖzhan 听到 :D:D
  • @BarbarosÖzhan 凡事都有时间,而且 长大了很多,所以我想应该拍一张新照片 :D

标签: python sql pandas oracle sqlalchemy


【解决方案1】:

这首先取决于表是如何创建的。默认情况下,无论该表的 DDL 是大写还是小写,Oracle 都会将其全部更改为大写并存储在数据库中。

这意味着,对于 Oracle,下面的 DDL 语句是相同的:

create table table1 (column1 VARCHAR2(20));
CREATE TABLE TABLE1 (COLUMN1 VARCHAR2(20));

具有这种创建 DDL 的表可以通过以下方式简单地查询:

SELECT COLUMN1 FROM TABLE1;
SELECT column1 FROM table1;

但是,不同的问题是,当表名或列用双引号指定时。

create table table1 ("column1" VARCHAR2(20));

然后,每次查询该列时,都必须始终通过这些引号再次查询它,并使用创建时的确切大小写:

SELECT "column1" FROM TABLE1;

关于 Python 代码,在 REPL 中似乎可以轻松地将双引号与单引号结合起来:

>>>input = 'SELECT "pred_pred" FROM XYZ'
>>>input
>>>'SELECT "pred_pred" FROM XYZ'

所以你可以用正确的代码来改变你的代码:

input = pd.read_sql_query('SELECT "pred_pred" FROM XYZ', connection)

为了确保我们在这里解决了正确的问题,您可能希望通过例如 SQL 开发人员和查询连接到您的数据库:

SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE UPPER(TABLE_NAME) = 'XYZ'

如果 column_name 不是全部大写,那么它是用双引号创建的,因此必须以相同的方式查询。 关于命名规则的进一步阅读https://docs.oracle.com/database/121/SQLRF/sql_elements008.htm#SQLRF00223

您已经在 cmets 中提到了使用 * 的解决方法 - 但使用 * 进行查询并在 Python 端执行投影部分似乎是个坏主意,因为它会提高数据库端所需的 IO 操作。

【讨论】:

    【解决方案2】:

    正如评论中所描述的,您应该只添加双引号来包裹您的columns,因为如果它没有用双引号包裹,oracle 会将其转换为大写。

    我认为您需要以下内容:

    input = pd.read_sql_query('SELECT "pred_pred" FROM XYZ', connection)
    

    因为您必须已经创建了 xyz 表,其中 column 用双引号括起来,所以它被存储为区分大小写的名称,即小写。

    请参阅此db<>fiddle demo 以获得更多说明。

    干杯!!

    【讨论】:

      猜你喜欢
      • 2015-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-04
      • 2015-09-04
      • 2018-01-22
      • 1970-01-01
      • 2014-10-07
      相关资源
      最近更新 更多