50 万行のテーブルの 1 つのフィールドを更新する、1 回限りの簡単な移行スクリプトを作成しています。
最初の ~25000 行のデータをフェッチするために行っている結合の完全なモデルを書き出すつもりはなかったので、 from_statement() 呼び出しを使用して UPDATE ステートメントを実行する方法を見つけようとしました。私自身の生のSQLですが、例が見つかりません。
それに伴い、SQLalchemy がエラーをスローしています。これが私の呼び出しとエラーの例です:
mydb = self.session()
mydb.query().from_statement(
"""
UPDATE my_table
SET settings=mysettings
WHERE user_id=myuserid AND setting_id=123
""").params(mysettings=new_settings, myuserid=user_id).all()
私が得るエラー:
Traceback (most recent call last):
File "./sample_script.py", line 111, in <module>
main()
File "./sample_script.py", line 108, in main
migrate.set_migration_data()
File "./sample_script.py", line 100, in set_migration_data
""").params(mysettings=new_settings, myuserid=user_id).all()
File "/usr/lib/pymodules/python2.6/sqlalchemy/orm/query.py", line 1267, in all
return list(self)
File "/usr/lib/pymodules/python2.6/sqlalchemy/orm/query.py", line 1361, in __iter__
return self._execute_and_instances(context)
File "/usr/lib/pymodules/python2.6/sqlalchemy/orm/query.py", line 1364, in _execute_and_instances
result = self.session.execute(querycontext.statement, params=self._params, mapper=self._mapper_zero_or_none())
File "/usr/lib/pymodules/python2.6/sqlalchemy/orm/query.py", line 251, in _mapper_zero_or_none
if not getattr(self._entities[0], 'primary_entity', False):
IndexError: list index out of range
アップデート
私はMySQLを使用しています。
サミーの提案に従って、私はこれを試しました:
mydb.execute(
"UPDATE mytable SET settings=:mysettings WHERE user_id=:userid AND setting_id=123",
{'userid': user_id, 'mysettings': new_settings}
)
これは効果がありませんでした。エラーは発生しませんが、行が変更されないため、ステートメントは実際には実行されていないようです。echo=True オプションからログに記録されたクエリを手動でカット アンド ペーストすると、データベース内の行が正常に更新されます。
更新 - 解決済み
Samy の提案は正しかったのですが、.execute() 呼び出しは「セッション」ではなく「エンジン」でのみ機能するため、これはうまく機能しました。
self.engine.execute(
"UPDATE mytable SET settings=:mysettings WHERE user_id=:userid AND setting_id=123",
{'userid': user_id, 'mysettings': new_settings}
)