質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

3回答

984閲覧

Python SQLite3 データベースへの登録 (行ごと/データフレーム全体、書込み/更新)

conan_ed

総合スコア3

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

1クリップ

投稿2023/10/22 03:04

編集2023/10/22 05:37

実現したいこと

・Python SQLite3 を使用してデータベースを作成し、運用したいと考えています
・データフレーム df で用意した値をデータベースに書き込み、ユーザーが変更できる仕組みを作りたい
※やりたいこと※
①行ごと( df内の各idごと) にまとめて書込む
②データフレームの内容を一括で書き込む

前提

Python SQLite3 を学習し日が浅く、独学で少しづつ理解を深めている状況です。
特にデータベースについては今回初めて扱います。

iddateitempricequantity
12000-01-01さくらんぼ10010
22000-01-01いちご20020
32000-01-01ぶどう30030
42000-01-01みかん40040
52000-01-01かき50050
62000-01-01りんご60060
72000-01-01なし70070

上記が使用するデータの初期値で、データフレームとして用意しました
idは固有の値です
1.空のデータフレームを作成
2.初期値を書き込む

ということをやりたいのですが、
[2.初期値を書き込む] の所で躓いています。
個別のデータとして execute('INSERT INTO を使用して書き込みはできたのですが、
例えば(1, '2000-01-01', 'さくらんぼ', 100, 10)をまとめて書込んだり、
データフレーム全体を書き込んだり、ということができていません。

困っている内容は、
①行ごと(1, '2000-01-01', 'さくらんぼ', 100, 10)で初期値を書き込む方法(INSERT INTO)
②データフレーム全体を初期値として書き込む方法(INSERT INTO)

全く知識の無いところからのスタートで、何日も手が止まってしまい困り果てています。
Python sqlite3 pandas その他もろもろ知識が不足していることは重々承知しております。
先輩方のお力添えを頂ければ幸いです<m(__)m>

発生している問題・エラーメッセージ

38行目にて下記エラー

例外が発生しました: ProgrammingError parameters are of unsupported type File "C:\python\webapp\codetest02.py", line 38, in <module> cur.executemany('INSERT INTO fruit_data VALUES(?,?,?,?,?)' , index_0) sqlite3.ProgrammingError: parameters are of unsupported type

該当のソースコード

python

1import pandas as pd 2import sqlite3 3 4#初期値をデータフレームとして用意 5list_df = pd.DataFrame({'id': [1 , 2 , 3 , 4 , 5 , 6 , 7], 6 'date': ['2000-01-01' , '2000-01-01' , '2000-01-01', '2000-01-01', '2000-01-01', '2000-01-01', '2000-01-01'], 7 'item': ['さくらんぼ', 'いちご' , 'ぶどう', 'みかん','かき','りんご' , 'なし'], 8 'price': [100 , 200 , 300 , 400 , 500 , 600 , 700], 9 'quantity': [10 , 20 , 30 , 40 , 50 , 60 , 70]}) 10 11# SQLiteに接続する 12conn = sqlite3.connect('fruit_data.db') 13# SQLiteを操作するためのカーソルを作成 14cur = conn.cursor() 15#変数query:の宣言 16query = "SELECT * FROM fruit_data" 17 18#デバッグの為、dbを一度初期化 19conn.execute('DROP TABLE IF EXISTS fruit_data') 20 21# テーブルを作成する 22cur.execute("CREATE TABLE IF NOT EXISTS fruit_data( \ 23 id INTEGER PRIMARY KEY, \ 24 date TEXT NOT NULL, \ 25 item TEXT NOT NULL, \ 26 price INTEGER NOT NULL, \ 27 quantity INTEGER NOT NULL)") 28 29#個別のデータではdb登録可能 30# cur.execute('''INSERT INTO fruit_data VALUES (1, '2000-01-01', 'さくらんぼ', 100, 10)''') 31 32#0行目index[0]をリストで取得・・・取得結果[1, '2000-01-01', 'さくらんぼ', 100, 10] 33index_0 = list_df.iloc[0].to_list() 34#0行目をタプルに変換・・・変換結果(1, '2000-01-01', 'さくらんぼ', 100, 10) 35tuple_index_0=tuple(index_0) 36 37#取得した行をリストで登録 38cur.executemany('INSERT INTO fruit_data VALUES(?,?,?,?,?)' , index_0) 39#取得した行をタプルで登録 40# cur.executemany('INSERT INTO fruit_data VALUES(?)' , tuple_index_0) 41 42# commitする 43conn.commit() 44# データベースをdfに書き出し表示する 45df = pd.read_sql_query(query,conn) 46print(df)

試したこと

個別のデータではdb登録可能でした…30行目
cur.execute('''INSERT INTO fruit_data VALUES (1, '2000-01-01', 'さくらんぼ', 100, 10)''')

行ごと登録の為、リストやタプルで取り出し、
executemany('INSERT INTO の所を色々と修正しましたがうまくいきませんでした。
32~38行目が試した内容です

補足情報(FW/ツールのバージョンなど)

python3.11
win11

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

sqlite3.ProgrammingError: parameters are of unsupported type

既に他の方の回答にあります通り、sqlite3.register_adapter(type, callable) を利用して、事前に変換器を登録しておきます。

python

1import numpy as np 2 3sqlite3.register_adapter(np.int64, int) 4 5cur.executemany('INSERT INTO fruit_data VALUES(?,?,?,?,?)' , [index_0]) # リストのリストを指定

②データフレーム全体を初期値として書き込む方法(INSERT INTO)

以下の場合、sqlite3.register_adapter(np.int64, int) は不要になります。(pandas.DataFrame.to_sql() の内部で自動変換されます)

python

1#変数query:の宣言 2query = "SELECT * FROM fruit_data" 3 4#デバッグの為、dbを一度初期化 5conn.execute('DROP TABLE IF EXISTS fruit_data') 6 7# テーブルを作成する 8cur.execute("CREATE TABLE IF NOT EXISTS fruit_data( \ 9 id INTEGER PRIMARY KEY, \ 10 date TEXT NOT NULL, \ 11 item TEXT NOT NULL, \ 12 price INTEGER NOT NULL, \ 13 quantity INTEGER NOT NULL)") 14 15list_df.to_sql(name='fruit_data', con=conn, if_exists='append', index=False) 16 17# データベースをdfに書き出し表示する 18df = pd.read_sql_query(query,conn) 19print(df) 20 21# id date item price quantity 22# 0 1 2000-01-01 さくらんぼ 100 10 23# 1 2 2000-01-01 いちご 200 20 24# 2 3 2000-01-01 ぶどう 300 30 25# 3 4 2000-01-01 みかん 400 40 26# 4 5 2000-01-01 かき 500 50 27# 5 6 2000-01-01 りんご 600 60 28# 6 7 2000-01-01 なし 700 70

①行ごと(1, '2000-01-01', 'さくらんぼ', 100, 10)で初期値を書き込む方法(INSERT INTO)

データフレーム全体を sqlite3 の既存テーブルに追加する場合と同様にできます。

python

1# list_df.iloc[[0]] はデータフレーム(pandas.DataFrame 型インスタンス)で、list_df.iloc[0] は pandas.Series 型インスタンスです 2list_df.iloc[[0]].to_sql(name='fruit_data', con=conn, if_exists='append', index=False)

投稿2023/10/22 04:33

編集2023/10/22 04:58
melian

総合スコア19840

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

conan_ed

2023/10/22 06:10

お忙しい中、①、②両方の回答を頂きましてありがとうございます。 回答頂いた、両方の動作が実現できました! pandas.DataFrame.to_sql()を使うという知識がありませんでしたので、 引数の詳細含めて今回勉強させて頂きます。 「list_df.iloc[[0]] はデータフレーム(pandas.DataFrame 型インスタンス)で、list_df.iloc[0] は pandas.Series 型インスタンスです」 とのコメントも参考になります。
guest

0

質問にあるような、更新や追加・削除が必要になるようなデータを、RDBとDFで扱うのは相性が悪いのでやめたほうがいいと思います。

たとえば、新たなデータを追加する場合、DFを更新して、そのデータをDBでも更新するわけですから、単なる二度手間です。
DBというのは、メモリに乗りきらなかったり、永続させたかったりするデータをプログラムの外で管理保存するための仕組みです。なので、更新や追加・削除は直接行ない、必要なデータは都度問い合わせで取得するのが正しいやりたかだと思います。

投稿2023/10/22 04:02

TakaiY

総合スコア12792

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

conan_ed

2023/10/22 05:23

お忙しい中、回答頂きましてありがとうございます。 ”更新や追加・削除が必要になるようなデータを、RDBとDFで扱うのは相性が悪いのでやめたほうがいい” というご意見、大変参考になります。 システム全体の構成を見直しながら、DB,DFの使いどころを見直したいと思います。 ありがとうございました。
guest

0

全部答えると丸投げに対応したことになってしまうので、ヒントとして①だけ答えます。

py

1index_0 = list_df.iloc[0].to_list()

ここで、index_0 の id, price, quantity は int型ではなく、
numpy.int64型になっています。
ですのでそのままではsqliteに挿入しようとしても、型の不一致でエラーになります。

np.int64型のデータを自動的にintに変換するには
sqlite3.register_adapter を使えばできます。

また、executemany メソッドの第2引数は、タプルのリストでなければなりません。

したがって、以下のようになります。

py

1import pandas as pd 2import sqlite3 3 4# numpy.int64 を int に変換して読み込む設定 5import numpy 6sqlite3.register_adapter(numpy.int64, lambda val: int(val)) 7 8#初期値をデータフレームとして用意 9list_df = pd.DataFrame({'id': [1 , 2 , 3 , 4 , 5 , 6 , 7], 10 'date': ['2000-01-01' , '2000-01-01' , '2000-01-01', '2000-01-01', '2000-01-01', '2000-01-01', '2000-01-01'], 11 'item': ['さくらんぼ', 'いちご' , 'ぶどう', 'みかん','かき','りんご' , 'なし'], 12 'price': [100 , 200 , 300 , 400 , 500 , 600 , 700], 13 'quantity': [10 , 20 , 30 , 40 , 50 , 60 , 70]}) 14 15# SQLiteに接続する 16conn = sqlite3.connect('fruit_data.db') 17# SQLiteを操作するためのカーソルを作成 18cur = conn.cursor() 19#変数query:の宣言 20query = "SELECT * FROM fruit_data" 21 22#デバッグの為、dbを一度初期化 23conn.execute('DROP TABLE IF EXISTS fruit_data') 24 25# テーブルを作成する 26cur.execute("CREATE TABLE IF NOT EXISTS fruit_data( \ 27 id INTEGER PRIMARY KEY, \ 28 date TEXT NOT NULL, \ 29 item TEXT NOT NULL, \ 30 price INTEGER NOT NULL, \ 31 quantity INTEGER NOT NULL)") 32 33 34#0行目index[0]をリストで取得・・・取得結果[1, '2000-01-01', 'さくらんぼ', 100, 10] 35index_0 = list_df.iloc[0].to_list() 36#0行目をタプルに変換・・・変換結果(1, '2000-01-01', 'さくらんぼ', 100, 10) 37tuple_index_0=tuple(index_0) 38 39#取得した行をタプルで登録 40print(tuple_index_0) 41# cur.executemany('INSERT INTO fruit_data VALUES(?,?,?,?,?)' , tuple_index_0) # <-リストでないのでエラー 42cur.executemany('INSERT INTO fruit_data VALUES(?,?,?,?,?)' , [tuple_index_0]) # <-リストにして渡す 43 44# commitする 45conn.commit() 46# データベースをdfに書き出し表示する 47df = pd.read_sql_query(query,conn) 48print(df)

投稿2023/10/22 03:42

編集2023/10/22 03:43
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

conan_ed

2023/10/22 05:36

お忙しい中、回答頂きましてありがとうございます。 丸投げ質問のような印象を与えてしまい、申し訳ありません。 現状の知識レベルと進捗を記載するつもりで、困っている内容を①~③まで記載してしまいました。 以後、気を付けます。(質問内容修正します) 頂いた回答にて確認させて頂き、意図する動作が得られました!ありがとうございます。 型についての意識が低く、numpy.int64型であることに気づきませんでした。 また、sqlite3.register_adapterを知りませんでしたので、今回勉強させて頂きます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問