DB Python

cx_oracle - Oracle で ora-01861 でハマる

cx_oracle - Oracle で ora-01861 でハマる

Pythonで cx_oracle ライブラリを使ってOracleデータベースにデータをinsertする際に

cx_Oracle.DatabaseError: ORA-01861 : literal does not match format string

のエラーが発生することがある。
特にOracle Cloudを初めて利用する際に発生するので、今回はこの ORA-01861 エラーの原因と対策について紹介する。


エラー原因

エラー原因

エラー内容を見ると、 ORA- で始まっているので、PythonではなくOracleで発生していることがわかる。

また literal does not match format string を訳すと「リテラルが書式文字列と一致しません」となるので何らかの書式が間違っていることが推測できる。

では何の書式がエラーになっているかというと、日付だ。

insertしようとしている日付の書式がOracle側と合っていないために ORA-01861 エラーが発生している。

書式も色々存在する。

書式
YYYYMMDD 20200113
YYYY年MM月DD日 2020年01月13日
DD-MM-YYYY 13-01-2020
DD-MON-RR 13-Jan-20

環境を確認するにはOracle上で以下のSQLを実行する。
するとNLS_DATE_FORMATの値がDD‐MON-RRと表示される。

select * from v$nls_parameters;

実はOracleの標準の日付書式が DD‐MON-RR となっており、YYYYMMDDYYYY-MM-DD 形式で日付を入れようとするとエラーになってしまうのだ。

Oracle Databaseのデフォルトの標準日付書式はDD‐MON-RRです。





「JanとかFebとか普段使わないのでどうしたらいいのか」

と思うかも知れないが、対策は存在する。


対策

対策

実は日付書式を気にしなくてもデータをinsertできる方法がある。
それはDateTime型を使うことだ。

実はPythonからOracleに接続するためのライブラリ cx_oracle には、Pythonのdatetime型とOracleのdatetime型を暗黙的に変換する機能があり、datetime型をそのままinsertできる。

PyMySQL の場合はdatetime型のままだとMySQLと型の不整合が起こるので、以下のように文字列に変換してから挿入していた。

now = datetime.datetime.now()
now_str = now.strftime('%Y-%m-%d %H:%M:%S')

しかしcx_oracleではinsertするレコードの1カラムがdatetime型でも文字列に変換する必要がない。

now = datetime.datetime.now()

日付を文字列ではなくdatetime型のままinsertすることで ORA-01861 のエラーを回避できる。

cx_Oracleはクラス datetime.datetime のオブジェクトの受け渡しをサポートしています。


まとめ

  • ora-01861 の原因は日付書式が間違っているから
  • cx_oracleを使うならdatetime型を文字列変換せずにそのままinsertすればエラーを回避できる



KRSW

駆け出し機械学習エンジニア。機械学習、DB、WEBと浅く広い感じ。 Junior machine learning engineer. Not a specialist but a generalist who knows DB, WEB too.

役に立ったらシェアしてくれると励みになります。
If you felt this article is useful, please share.
にほんブログ村 IT技術ブログへ

-DB, Python
-,

Translate »

Copyright© ITips , 2020 All Rights Reserved.