簡體   English   中英

SQLAlchemy:成功插入但隨后引發異常

[英]SQLAlchemy: successful insertion but then raises an exception

我正在對FirebirdSQL運行SQLAlchemy,當我在項目中執行insert命令時,SQLAlchemy在從連接執行返回時引發異常。 但是 ,正在構建並成功執行insert查詢。 查詢數據庫顯示實際正在正確插入項目。

編輯:我現在正在深入研究fbcore.py模塊,並檢查valuevartypevalue表明問題可能是用於生成主鍵ID的SEQUENCE項目返回其數據的問題。 vartypeSQL_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.pyexecute 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM