【问题标题】:How to write pandas dataframe to oracle database using to_sql?如何使用 to_sql 将 pandas 数据框写入 oracle 数据库?
【发布时间】:2018-05-12 10:57:57
【问题描述】:

我是一个新的 oracle 学习者。我正在尝试将 pandas 数据框写入 oracle 表中。上网查了一下,发现代码本身很简单,但是不知道为什么我的代码不行。

我已经从本地文件中读取了 pandas 数据框:

import cx_Oracle
import pandas as pd
import os

dir_path = os.path.dirname(os.path.realpath("__file__"))
df = pd.read_csv(dir_path+"/sample.csv")

现在打印df,数据帧df应该是这样的:

   DATE            YEAR     MONTH      SOURCE      DESTINATION
0  11/1/2017 1:00  2017     1          AL          CO  
1  11/2/2017 1:00  2017     5          GA          ID  
2  11/3/2017 1:00  2017     12         GA          MO    

然后我使用 cx_Oracle 创建与数据库的连接,它可以工作。接下来我尝试将数据帧 df 写入表 TEST。该表TEST是oracle数据库中已经存在的空表,oracle中的列包括DATE、YEAR、MONTH、SOURCE、DESTINATION。所有数据类型都与 df 样本数据匹配。我的代码如下:

conn_str = u'account/password@host:1521/server'
conn = cx_Oracle.connect(conn_str)

# Write records stored in a DataFrame to a oracle database
df.to_sql('TEST', conn, if_exists='replace') # the error shows here

conn.close()

显示错误:

DatabaseError: sql 'SELECT name FROM sqlite_master 执行失败 WHERE type='table' AND name=?;': ORA-01036: 非法变量 姓名/号码

如何解决问题?非常感谢您的宝贵时间!

【问题讨论】:

    标签: oracle pandas dataframe cx-oracle pandas-to-sql


    【解决方案1】:

    我在 SO 上看到过类似的问题 - 当您尝试使用 cx_Oracle 创建的连接对象写入 Oracle DB 时会发生这种情况。

    尝试使用 SQL Alchemy 创建连接:

    import cx_Oracle
    from sqlalchemy import types, create_engine
    
    conn = create_engine('oracle+cx_oracle://scott:tiger@host:1521/?service_name=hr')
    
    df.to_sql('TEST', conn, if_exists='replace')
    

    【讨论】:

    • 感谢您的回复。我试过了,然后它显示 DatabaseError: (cx_Oracle.DatabaseError) ORA-01950: noprivilege on tablespace 'xxx_DATA' [SQL: 'INSERT INTO 'TEST' ("index", "DATE", "YEAR", "MONTH", ...) VALUES (:"index", :"DATE", :YEAR,...)]
    • @HavenShi,这是一个不同的故事。这意味着您(或您的 DBA)必须为该 oracle 用户在该表空间上添加配额。我认为您的原始问题已得到解答;-)
    • ,你能多解释一下表空间吗?可以直接写入oracle表TEST,漏掉了什么?
    • 看起来它需要小写的表名,如果表存在,它不喜欢它。将所有内容都创建为 CLOB,这很烦人。
    • @Superdooperhero,您可能想查看this answer ;)
    【解决方案2】:

    我可以使用以下代码加载 Oracle 表:

    import pandas as pd
    import os
    
    creds = {}
    creds['tns_admin'] = 'Wallet_Path'
    creds['sid'] = 'dev_low'
    creds['user'] = 'username'
    creds['password'] = pwd
    
    os.environ['TNS_ADMIN'] = creds['tns_admin']
    
    
    uri = 'oracle+cx_oracle://' + creds['user'] + ':' + creds['password'] + '@' + creds['sid']
    df = pd.read_csv("test.csv")
    df.to_sql('test', uri, schema='PRD', if_exists='replace')
    

    我们需要构建和传递一个 URI,而不是连接。

    注意:新的 Oracle 数据库(自治)需要钱包,所以我们需要在 TNS_ADMIN 环境变量中设置钱包路径。

    另外,我不必导入 cx_Oracle,我仔细检查了

    为了确保我没有被愚弄,我放弃了桌子并提交了

    我执行了上面的代码,它用数据创建了新表。

    【讨论】:

      【解决方案3】:

      参考this 解决方案后,我可以使用以下步骤完成此操作。

      from sqlalchemy.engine import create_engine
      
      DIALECT = 'oracle'
      SQL_DRIVER = 'cx_oracle'
      USERNAME = 'your_username' 
      PASSWORD = 'your_password'
      HOST = 'subdomain.domain.tld' 
      PORT = 1521 
      SERVICE = 'your_oracle_service_name'
      ENGINE_PATH_WIN_AUTH = DIALECT + '+' + SQL_DRIVER + '://' + USERNAME + ':' + PASSWORD +'@' + HOST + ':' + str(PORT) + '/?service_name=' + SERVICE
      
      engine = create_engine(ENGINE_PATH_WIN_AUTH)
      

      成功创建 SQLAlchemy 引擎后,您可以将其传递给 pandas to_sql() 函数。

      df.to_sql('name_of_sql_table',engine,schema='your_schema')
      

      【讨论】:

        猜你喜欢
        • 2017-08-01
        • 2015-08-18
        • 2018-07-28
        • 2021-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-18
        • 2021-03-06
        相关资源
        最近更新 更多