pagetakaBlog

最近リフォームと鳥取県日南町の記事多め。写真、PC、ネット等の話題も

Pythonで DataFrame → MariaDB へ to_sql 書き込み時に、複数 index 設定で悶絶…からの成功メモ

データベースつかうのにindexがないというのは便利さを半分放棄したような状態です。普段なら苦も無くできるコトが一定の条件下で失敗。爺は複数のindexをつくろうとして、悶絶したです。何とか解決できたので、備忘録としてUPします。


MariaDB のテーブル X に複数 index を付けようとして失敗。原因は to_sql の仕様だった…

Python で作った DataFrame(df)を pandas.to_sql() で MariaDB のテーブル X に書き込むついでに、項目 A・B に index を複数作ろうとして悶絶した記録です。

AI Copilot に相談したところ、

  • to_sql ではテーブル作成時に作れる index は「単独 index 1つ」または「複合 index 1つ」だけ-
  • 複数 index を作りたいなら、pymysql などで普通に SQL を for で回す方が安全

というアドバイスをもらいました。

確かに、エラーが出たときにどの SQL が悪いのか分かりやすいし、DDL(CREATE INDEX)は暗黙 commit されるので commit も不要。なるほど…と膝を打った次第です。

普通に SQL を書いて for で回すのが安全だった話

Python+DataFrame+to_sqlでデータをULした部分と、pymysqlでSQL書いてwithとforでindex作った部分のスクリプトです。事前に必要な、データベースの設定、 sqlalchemy、pymysql のimportは省いてます。悪しからず。

# df にはすでにデータが入っているものとして ---
df.to_sql(
    name = 'Table_X',
    con = engine,   # この接続は明示的に close 不要(session 使用時は必要)
    if_exists = "replace",
    index = False
)

# 作成したい index をリスト化 コラム名は適宜
indexes = [
    "CREATE INDEX idx_cd ON Table_X(cd);",
    "CREATE INDEX idx_num ON Table_X(num);",
    "CREATE INDEX idx_date ON Table_X(date);",
    "CREATE INDEX idx_cd_date ON Table_X(cd, date);",
]

# index 作成:単純に for で回すのが安全
with pymysql.connect(**DB0) as con:  
    with con.cursor() as cur:
        for sql in indexes:
            try:
                cur.execute(sql)
            except Exception as err_msg:
                print(f'\n例外発生: {err_msg}')
                time.sleep(3)
            finally:
                pass  # exit は不要

with をつかうと締めくくりで横着できる

  • commit() → 不要(DDL は自動 commit)
  • cur.close() → with で自動 close
  • con.close() → with で自動 close

Python の with は本当に便利。