今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、cx_oracleでinsertにてハマったエラーについての日。

目次

とある日

Pythonで、Oracle DatabaseにアクセスしてSQLを実行するために、cx_Oracleというモジュールを使用して、開発を行っていた。

そこで、ユーザが入力した情報をcx_OracleOracleに対してINSERT文しようとしたときに起こった悲劇(やらかした話)。

悲劇

このINSERT文を実行。

sql = """
    INSERT INTO 
        users_detail (
        user_id,
        name,
        email,
        password,
        gender_id,
        image_path
    VALUES(
    :user_id,
    :name,
    :email,
    :password,
    (SELECT gender_id FROM genders WHERE kind = :gender),
    '..'
    )
"""

test = {
    "user_id":16,
    "name":"test2",
    "email":"test2@test2",
    "password":"password",
    "gender":"男性",
    "image_path":"TEST"
}


try:
    with conn.cursor() as cursor:
        conn.begin()
        cursor.execute(sql,test)
        result_data = cursor.fetchall()
        conn.commit()
        print("END")
    except Exception as identifier:
        print(identifier)

これを実行すると下記のエラーが出る。

DEBUG : VARNAME : identifier VAR:not a query

和訳すると、それはクエリじゃないって言われる。

原因

result_data = cursor.fetchall()

この行がエラーの原因だった。

INSERTやUPDATEなど、結果がないものに関してfetchallを使用するとエラーになる。

Cursor.``fetchall()

クエリ結果のすべての(残りの)行をフェッチし、それらをタプルのリストとして返します。使用可能な行がなくなると、空のリストが返されます。データベースからの内部読み取りはarraysizeに対応するバッチで行われるため、カーソルのarraysize属性がこの操作のパフォーマンスに影響を与える可能性があることに注意してください。

前の呼び出しでexecute() 結果セットが生成されなかった場合、または呼び出しがまだ発行されていない場合は、例外が発生します。

例については、フェッチメソッドを参照してください。

リファレンスにもしっかり書いていたが、読み逃していた。

これに数時間悩まされた。

はじめ、バインド変数がうまく行かないと思ってそのあたりをデバッグしてたので、fetchallのミスに気づかなかった。

ほかの、PHPでのMySQL接続やPythonMySQL接続のほうが簡単であり機能が充実してると思った。

cx_Oracleは少し使いづらい気がした。