(0)目次&概説
(1) エラー対応1:sqlalchemy.exc.ArgumentError
(1-1) 発生状況・エラーメッセージ
(1-1-1) エラーメッセージ
(1-1-2) エラーとなったソース
(1-2) 原因
(1-3) 対処方法
(2) エラー2:Could not reflect: requested table(s)
(2-1) 発生状況・エラーメッセージ
(2-1-1) エラーメッセージ
(2-1-2) エラーとなったソース
(2-2) 原因
(2-3) 対処方法
(1) エラー対応1:sqlalchemy.exc.ArgumentError
(1-1) 発生状況・エラーメッセージ
Web上で公開されているcsvデータのURLに対して「requests」パッケージの「get」関数を用いてデータを取得し、それをPandasの「read_csv」関数でDataframeに入れてから「to_sql」関数でOracleDBのテーブルにINSERTしようとした際にこのエラーに遭遇しました。
(1-1-1) エラーメッセージ
sqlalchemy.exc.ArgumentError: Could not parse rfc1738 URL from string '[Table name]'
(1-1-2) エラーとなったソース
import datapackage import cx_Oracle import sqlalchemy import pandas as pd import requests from io import StringIO def main(): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'} url = 'https://[your URL].json' dp = datapackage.Package(url) res = dp.resources from sqlalchemy import create_engine engine = create_engine('oracle://[your schema]:[your password]@[hostname]:[port]/[sid]') for res in res: if res.tabular: if res.descriptor['datahub']['type'] == 'derived/csv': s=requests.get(res.descriptor['path'], headers= headers).text df = pd.read_csv(StringIO(s)) print(res.descriptor['path']) df.to_sql(engine,'CMTB_COMPANY_MASTER',if_exists='replace',index=False) if __name__ == '__main__': main()
(図101)
(1-2) 原因
引数の順番が正しく指定されていなかったためでした。「to_sql」関数は暗黙の「self」を除いた場合の第1引数は「SQLのテーブル名」で第2引数が”create_engine”関数の実行結果(sqlalchemy.engine.base.Engine)ですが、上記の例ではこれが逆になっているためにエラーとなっています。
(※本来はEngineインスタンス(「Engine(oracle://[your schema]:***@[hostname]:[port]/orcl)」のような文字列)を想定していた所、テーブル名を誤って引数として与えたため)
参考:Pandasの「to_sql」の説明
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html
(1-3) 対処方法
上記の第1引数”engine”と第2引数の”CMTB_COMPANY_MASTER”の順番を逆にしたら、当該エラーは起こらなくなりました。
(ただし、今度は後述の別のエラーに遭遇しますが・・)
df.to_sql('CMTB_COMPANY_MASTER',engine,if_exists='replace',index=False)
(2) エラー2:Could not reflect: requested table(s)
(2-1) 発生状況・エラーメッセージ
(2-1-1) エラーメッセージ
sqlalchemy.exc.InvalidRequestError: Could not reflect: requested table(s) not available in Engine(oracle://[your schema]:***@[hostname]:[port]/orcl): ([your table name])
(2-1-2) エラーとなったソース
前の章からの主な差分箇所は以下です。
①SQLAlchemyの”create_engine”でEngineオブジェクトを作りDB接続しています。
②上記のEngineオブジェクトを用いてPandasの「to_sql」でDBのテーブルにレコードをINSERTしています。
import datapackage import cx_Oracle import sqlalchemy import pandas as pd import requests from io import StringIO def main(): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'} url = 'https://[your URL].json' dp = datapackage.Package(url) res = dp.resources from sqlalchemy import create_engine engine = create_engine('oracle://[your schema]:[password]@[hostname]:[port]/[sid]') for res in res: if res.tabular: if res.descriptor['datahub']['type'] == 'derived/csv': s=requests.get(res.descriptor['path'], headers= headers).text df = pd.read_csv(StringIO(s)) print(res.descriptor['path']) df.to_sql('CMTB_COMPANY_MASTER',engine,if_exists='replace',index=False) if __name__ == '__main__': main()
(図201)
(2-2) 原因
「引数のテーブル名」と「DB側のテーブル名」がマッチしていない事が原因でした。どうやらDB側ではテーブル名を小文字に変換しているため、引数で大文字のテーブル名を与えると不一致でエラーとなるようです。実際に警告としてもその旨の文章が出ており「Consider using lower case table names」と小文字を推奨する記載も見受けられます。
C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\site-packages\pandas\io\sql.py:1336: UserWarning: The provided table name 'CMTB_COMPANY_MASTER' is not found exactly as such in the database after writing the table, possibly due to case sensitivity issues. Consider using lower case table names. warnings.warn(msg, UserWarning)
(2-3) 対処方法
テーブル名をstr型の変数に代入して「.lower()」メソッドで小文字変換することでミスマッチを防止できます。
■修正前:
df.to_sql('CMTB_COMPANY_MASTER',engine,if_exists='replace',index=False)
■修正後:
tab_name = 'CMTB_COMPANY_MASTER' df.to_sql(tab_name.lower(),engine,if_exists='replace',index=False)
(図202)
・エラーは解消
↓
・テーブルにも正常にレコードが格納されている