PythonからSQLite使用時にUPSERTが使いたくなって調べてみましたが、使えるようです。
UPSERT is a special syntax addition to INSERT that causes the INSERT to behave as an UPDATE or a no-op if the INSERT would violate a uniqueness constraint. UPSERT is not standard SQL. UPSERT in SQLite follows the syntax established by PostgreSQL. UPSERT syntax was added to SQLite with version 3.24.0 (2018-06-04). SQLite Query Language: upsert
ただ環境によっては、より古いバージョンのSQLiteしか入っていないことがあると思います。
>>> import sqlite3
>>> conn = sqlite3.connect(":memory:")
>>> conn.execute("select sqlite_version()").fetchone()
(u'3.22.0',)
解決策
古いバージョンを前提に対応方法をググると、「SQLiteでUPSERTの場合は、INSERT or REPLACE
文にすればよい」という記事がありますが、これは少し乱暴な書き方かと思います。
一般的にUPSERTでやりたいことについて、厳密には二種類あります:
- ケースA) 既存レコードを入れ替える際、既存レコードのカラム値を捨てる
- ケースB) 既存レコードを入れ替える際、既存レコードの他のカラム値を維持する
INSERT or REPLACE
が使えるのは、A)の場合のみになります。
今回はB)にしたかったので、こう解決しました:
- INSERTとUPDATEでSQLを2つに分けて、INSERT→UPDATEの順に実行
- INSERTでは、レコードを作るのみとする(キー値のみ入れる)
- UPDATEで、値を入れる ※直前のINSERT時と同じWHERE条件を使う
参考
記事の内容はあくまで個人の考えに基づくものであり、組織を代表するものではありません。