【问题标题】:SQLAlchemy raises TypeError when an INSERT returns no rows?当 INSERT 不返回任何行时,SQLAlchemy 会引发 TypeError?
【发布时间】:2013-01-16 00:15:34
【问题描述】:

我有一个这样的插入语句:

insert = MyTable.insert()
row = {"foo": 42}
result = cxn.execute(insert, row)

但 Postgres 触发器将插入从 mytable 重定向到新表,因此插入语句实际上并没有返回任何内容:

# INSERT INTO mytable VALUES (DEFAULT, 'stuff') RETURNING LASTVAL();
 lastval 
---------
(0 rows)

这会导致 SQLAlchemy (0.8b2) 引发 TypeError: 'NoneType' is not subscriptable。当DefaultExecutionContext 尝试获取插入行的主键时,似乎正在发生这种情况。

这是一个应该报告的错误吗?有什么办法可以解决这个问题,告诉 SQLAlchemy 不要期望返回值?

回溯

… snip… 
  File "myfile.py", line 85, in store
    result = cxn.execute(insert, row)
  File ".../sqlalchemy/engine/base.py", line 664, in execute
    params)
  File ".../sqlalchemy/engine/base.py", line 764, in _execute_clauseelement
    compiled_sql, distilled_params
  File ".../sqlalchemy/engine/base.py", line 899, in _execute_context
    context._fetch_implicit_returning(result)
  File ".../sqlalchemy/engine/default.py", line 697, in _fetch_implicit_returning
    ipk.append(row[c])
TypeError: 'NoneType' object is not subscriptable

Postgres 触发器

CREATE OR REPLACE FUNCTION mytable_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO mytable_cur VALUES (NEW.*);
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER mytable_insert_trigger
    BEFORE INSERT ON mytable
    FOR EACH ROW EXECUTE PROCEDURE mytable_insert_trigger();

【问题讨论】:

    标签: python postgresql sqlalchemy


    【解决方案1】:

    你在这里违反了合同。针对 Postgres 后端,SQLAlchemy 将倾向于使用 INSERT ... RETURNING 以便它可以检索例如来自生成的序列的值。您正在插入一行,但却在撒谎。

    基于the documentation,我认为您想使用INSTEAD OF 触发器而不是BEFORE,并让它返回NEW 行不变。 Postgres 将假定您执行了任何必要的插入操作,并将返回的行返回给客户端。

    【讨论】:

    • INSTEAD OF 将是理想的......但我被困在 Postgres 8.4 上,所以这不是一个选择:(
    【解决方案2】:

    是的,您可以通过关闭implicit_returning 来回退到获取最后插入的id 的旧系统,您可以对表执行此操作:

    Table('sometable', metadata, ... columns ..., implicit_returning=False)
    

    将会发生什么,假设这是一个直接的 SERIAL 主键,它将事先显式执行“tablename_id_seq”,并在 INSERT 语句中使用该值。

    【讨论】:

      猜你喜欢
      • 2021-12-19
      • 2020-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多