[英]SQLAlchemy: successful insertion but then raises an exception
我正在對FirebirdSQL運行SQLAlchemy,當我在項目中執行insert
命令時,SQLAlchemy在從連接執行返回時引發異常。 但是 ,正在構建並成功執行insert
查詢。 查詢數據庫顯示實際正在正確插入項目。
編輯:我現在正在深入研究fbcore.py
模塊,並檢查value
和vartype
的value
表明問題可能是用於生成主鍵ID的SEQUENCE
項目返回其數據的問題。 vartype
是SQL_LONG
,但實際值是[<an integer>]
,其中<an integer>
是我為自動遞增主鍵而創建的序列生成器返回的值(例如[14]
)。 這表明,我認為這個問題應該通過固定是可以解決,但我不知道該怎么做。 生成器似乎在數據庫本身內正常工作,但在返回SQLAlchemy時導致問題。
有關詳細信息,請參閱下面的現有實現和堆棧跟蹤。
我的代碼:
class Project:
# (I've snipped project instantiation, where engine connection, table, etc. are configured)
def save_project(self, id_=None, title=None, file_name=None, file_location=None):
# Build the dictionary of values to store
values = {}
if title is not None:
values['title'] = title
if file_name is not None:
values['file_name'] = file_name
if file_location is not None:
values['file_location'] = file_location
# Simplification: I account for the case that there *is* data---skipping that here
# Execute the correct kind of statement: insert or settings_update.
if id_ is None:
statement = self.table.insert()
else:
statement = self.table.update().where(self.table.c.id == id_)
result = self.connection.execute(statement, values)
# If we inserted a row, get the new primary key. Otherwise, return
# the one specified by the user; it does not change on settings_update.
project_id = result.inserted_primary_key if result.is_insert else id_
追溯:
File "/Users/chris/development/quest/workspace/my_project/data/tables.py", line 350, in save_project
result = self.connection.execute(statement, values)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 720, in execute
return meth(self, multiparams, params)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/sql/elements.py", line 317, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 817, in _execute_clauseelement
compiled_sql, distilled_params
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 947, in _execute_context
context)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 1111, in _handle_dbapi_exception
util.reraise(*exc_info)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/util/compat.py", line 168, in reraise
raise value
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 940, in _execute_context
context)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/sqlalchemy/dialects/firebird/kinterbasdb.py", line 106, in do_execute
cursor.execute(statement, parameters or [])
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 3323, in execute
self._ps._execute(parameters)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 2991, in _execute
self.__Tuple2XSQLDA(self._in_sqlda, parameters)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 2782, in __Tuple2XSQLDA
sqlvar.sqlscale)
File "/Users/chris/.virtualenvs/my_project/lib/python3.3/site-packages/fdb/fbcore.py", line 2266, in _check_integer_range
if (value < vmin) or (value > vmax):
TypeError: unorderable types: list() < int()
我還不熟悉SQLAlchemy,看看為什么這是一個問題; 我的陳述風格與教程中的風格非常相似。 這似乎是如何傳遞參數的問題 - 可能是關於使用dict而不是關鍵字參數的問題? 但是在文檔中沒有關於如何處理參數的信息,這表明我在這里有任何不妥之處 - 從我在那里看到的東西似乎是正確的。
我也嘗試過使用self.table.insert().values(values)
而不是將values
term傳遞給execute
方法,結果相同(正如我所料)。
編輯:我注意到在fbcore.py
中execute
docstring時,如果傳遞給方法的參數沒有作為列表或元組給出,則會引發TypeError。 這是一個尚未在文檔中反映出來的變化嗎?
編輯2:作為評論說明,堆棧跟蹤表明它正在針對kinterbasdb驅動程序運行,盡管我已明確配置引擎使用fdb運行。 這對我來說也很困惑。
正如我可能預料的那樣,特別是一旦我發現問題是該行按預期插入但隨后用UPDATE
函數調用,問題就是一些相關的代碼。 我將結果作為project_id
返回(正如您在上面的代碼中看到的那樣),並且由於完全不相關的原因(與Blinker信號有關),該方法再次被調用,返回值為project_id
,我已設置從而:
project_id = result.inserted_primary_key if result.is_insert else id_
此行的正確版本僅略有不同:
project_id = result.inserted_primary_key[0] if result.is_insert else id_
從SQLAlchemy文檔 (強調我的):
返回剛剛插入的行的主鍵。
返回值是與目標表中的主鍵列列表對應的標量值列表。
此處的返回值必須是列表,因為主鍵可以是數據庫中多個字段的組合。 (這對我來說應該是顯而易見的;很明顯我在一年多的時間里沒有做過嚴肅的數據庫工作。)由於這種情況下的主鍵是單個值,我只是選擇了該值並將其返回,問題是解決。
當然,現在我必須去追捕那個Blinker信號問題 - 這個方法不應該被調用兩次 - 但是c'est la vie ...
我一直在查看SQL Alchemy文檔,我想知道你是否應該這樣做:
if id_ is None:
statement = self.table.insert()
else:
statement = self.table.update().where(self.table.c.id == id_)
statement = statement.values(title=title, file_name=file_name, file_location=file_location)
result = self.connection.execute(statement)
即:不是將字典傳遞給執行,而是將其作為語句的一部分(如插入表達式所示)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.