KOSEN{BLOG}について

pythonを使って、csv=>pandas=>sqlite3に入れるときに起きた "sqlite3.IntegrityError: datatype mismatch" の強引な解消法

授業の一環でpythonを使ってsqlite3を弄ってた際に起きたエラーとその解消法についてまとめています。

環境

  • Python3 (3.7.5)
  • pandas
  • sqlite3

問題が起きた経緯

csvファイルに書かれてあるデータをpythonとpandasとsqlite3を使ってデータベースに打ち込む作業をしていました。

csvの中身のサンプルはこんな感じです

PID,Name,Sex
1000001,江﨑 喬祐,男
1000002,佐藤 太郎,男
1000003,田中 宏和,男

最初はこのcsvを読み込んでpandasにぶち込んだ後、

CREATE TABLE PERSONS(Pid integer, Name string, Sex string)

のテーブルに対して入れていました。この時点では特に問題は起きませんでした。

しかし、上のテーブルのスキーマを

CREATE TABLE PERSONS(Pid integer PRIMARY KEY, Name string, Sex string);

のように、最初のPidを主キーにして同じようにpandasからcsvをsqlite3に打ち込もうとすると、

sqlite3.IntegrityError: datatype mismatch

というエラーがpythonで吐き出されてしまいました。

解決方法

エラーの原因を調べてみるとこちらのサイトにたどり着きました。おそらく、primary keyにする前は、stringやtext型の”2″とかも忖度してinteger型に変換し代入してくれていましたが、primary keyにすると忖度してくれないようです。

sqlite3に保存しようとしているデータ(Pid)がinteger型になっていないため起きたエラーだとわかったので、今のデータの型を調べてみると、

PIDは

<class 'numpy.int64'>

という型になっていました。pandasにcsvを入れるとpandas内部にあるクラス Dataframeにcsvが変換して格納されます。Dataframe内の型を調べてみると、(PID)については上記のように ’numpy.int64′ と、numpyのライブラリ内にあるint64というものになっていました。一応、intっぽいものにはなっているのですが、python規格のintに直していきます。

PID,Name,Sex
1000001,江﨑 喬祐,男
1000002,佐藤 太郎,男
1000003,田中 宏和,男
1000004,田中 太郎,男

csv はこちら

import sqlite3
import pandas
import numpy

# csvをpandasに格納
persons = pandas.read_csv(csv_path)

# データの数だけループを回す
# 今回は、データの数は4行(PID,Name,Sexは自動的に除かれる)
for i in range(len(persons)):
  set_data = []
  
  # 1行の中身について、見る
  for person in persons.iloc[i]:
    # もし、データがnumpy.int64だったらintへ変換する
    if type(person) == numpy.int64: 
      person = int(person)
    
    # numpy.int64だったらintに変換後、それ以外の型だったら何もせず配列にappend
    set_data.append(person)
  self.cursor.execute("INSERT INTO PERSONS values( ?, ?, ?)", set_data) 

このように、csvの1つの要素の型が、numpy.int64だったら、強引にintに変換してあげることでエラーがなくなりました。

コメントを残す

メールアドレスが公開されることはありません。