python - 无法正确读取Python中的SQL表: varchar columns imported as comma-separated characters/tuples

标签 python sql pandas oracle jaydebeapi

我使用以下代码连接到 Oracle 数据库:

jar = ojdbc8.jar path
jvm_path = jvm.dll path
args = '-Djava.class.path=%s' % jar
jpype.startJVM(jvm_path, args)
con = jaydebeapi.connect("oracle.jdbc.driver.OracleDriver", url,[user, password], jar)

连接工作正常,但数据返回于 this odd format .

pd.read_sql("SELECT * FROM table1", con)

产量

+---+-----------------+-----------------+-----------------+
|   | (C,O,L,U,M,N,1) | (C,O,L,U,M,N,2) | (C,O,L,U,M,N,3) |
+---+-----------------+-----------------+-----------------+
| 1 | (t,e,s,t)       | (t,e,s,t,2)     | 1               |
+---+-----------------+-----------------+-----------------+
| 2 | (f,o,o)         | (b,a,r)         | 100             |
+---+-----------------+-----------------+-----------------+

数字和日期已正确导入,但 varchar 列未正确导入。我尝试了不同的表,所有的表都有这个问题。

我在任何地方都没有见过这样的事情。希望你能帮助我。

最佳答案

使用 jaydebeapi 时这似乎是一个问题与 jpype 。当以与您相同的方式连接到 Oracle 数据库时,我可以重现此情况(在我的例子中是 Oracle 11gR2,但由于您使用的是 ojdbc8.jar ,我想其他版本也会发生这种情况)。

有多种方法可以解决此问题:

更改您的连接

由于错误似乎只发生在特定的包组合中,因此最明智的做法是尝试避免这些错误,从而完全避免错误。

  1. 替代方案 1:使用 jaydebeapi没有jpype :

    如上所述,我仅在使用 jaydebeapi 时观察到这一点与 jpype 。然而,就我而言,jpype根本不需要。我有.jar在本地文件,我的连接在没有它的情况下工作正常:

    import jaydebeapi as jdba
    import pandas as pd
    import os
    
    db_host = 'db.host.com'
    db_port = 1521
    db_sid = 'YOURSID'
    
    jar=os.getcwd()+'/ojdbc6.jar'
    
    conn = jdba.connect('oracle.jdbc.driver.OracleDriver', 
                    'jdbc:oracle:thin:@' + db_host + ':' + str(db_port) + ':' + db_sid, 
                    {'user': 'USERNAME', 'password': 'PASSWORD'}, 
                    jar
                    )
    
    df_jay = pd.read_sql('SELECT * FROM YOURSID.table1', conn)
    
    conn.close()
    

    就我而言,这工作正常并正常创建数据帧。

  2. 替代方案 2:使用 cx_Oracle相反:

    如果我使用 cx_Oracle 也不会出现此问题连接到 Oracle 数据库:

    import cx_Oracle
    import pandas as pd
    import os
    
    db_host = 'db.host.com'
    db_port = 1521
    db_sid = 'YOURSID'
    
    dsn_tns = cx_Oracle.makedsn(db_host, db_port, db_sid)
    cx_conn = cx_Oracle.connect('USERNAME', 'PASSWORD', dsn_tns)
    
    df_cxo = pd.read_sql('SELECT * FROM YOURSID.table1', con=cx_conn)
    
    cx_conn.close()
    

    注意:对于cx_Oracle要工作,您必须拥有 Oracle Instant Client已安装并正确设置(参见 cx_Oracle documentation for Ubuntu )。

事后修复数据框:

如果由于某种原因,您无法使用上述连接替代方案,您也可以转换您的数据框。

  • 替代方案 3:连接元组条目:

    您可以使用''.join()convert tuples to strings 。您需要对条目和列名称执行此操作。

    # for all entries that are not None, join the tuples
    for col in df.select_dtypes(include=['object']).columns:
        df[col] = df[col].apply(lambda x: ''.join(x) if x is not None else x)
    
    # also rename the column headings in the same way
    df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True)
    
  • 替代方案 4:更改列的数据类型:

    作者:changnig dtype来自 object 的受影响列至string ,所有条目也将被转换。请注意,这可能会产生不需要的副作用,例如改变None值字符串 <N/A> 。此外,您还必须单独重命名列标题,如上所述。

    for col in df.select_dtypes(include=['object']).columns:
        df[col] = df[col].astype('string')
    
    # again, rename headings
    df.rename(columns=lambda x: ''.join(x) if x is not None else x, inplace=True)
    
  • 所有这些应该产生或多或少相同的 df最后(除了 dtypes 和可能的 None 值替换):

    +---+---------+---------+---------+
    |   | COLUMN1 | COLUMN2 | COLUMN3 |
    +---+---------+---------+---------+
    | 1 | test    | test2   | 1       |
    +---+---------+---------+---------+
    | 2 | foo     | bar     | 100     |
    +---+---------+---------+---------+
    

    关于python - 无法正确读取Python中的SQL表: varchar columns imported as comma-separated characters/tuples,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66691194/

    相关文章:

    python - sys.version_info 对于 Python 版本检查是否可靠?

    python - 制作一个 n 列的数组,其中每个连续的行增加一个

    python - 从 Locust 获取单个任务的统计信息

    php - 使用 mysqli 运行多个查询

    php - Mysql (MariaDB) 每次查询与从 View 读取?

    python - Django 中的内部连接

    python - Pandas agg 根据数据类型定义指标

    python - 如何在 output.csv 文件中包含 "for"循环变量

    python - 过滤异常值 - 如何使基于中值的 Hampel 函数更快?

    python - 如何在python中获取旋转线的角度