データベースつかうのに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 は本当に便利。