默认值在SQLAlchemy + PostgreSQL + aiopg + psycopg2中不起作用

时间:2015-03-06 14:36:09

标签: postgresql sqlalchemy default psycopg2

我在SQLAlchemy中发现了一个意外的行为。我使用以下版本:

  • SQLAlchemy (0.9.8)
  • PostgreSQL (9.3.5)
  • psycopg2 (2.5.4)
  • aiopg (0.5.1)

这是示例的表定义:

import asyncio
from aiopg.sa import create_engine
from sqlalchemy import (
  MetaData,
  Column,
  Integer,
  Table,
  String,
)
metadata = MetaData()

users = Table('users', metadata,
  Column('id_user', Integer, primary_key=True, nullable=False),
  Column('name', String(20), unique=True),
  Column('age', Integer, nullable=False, default=0),
)

现在,如果我尝试对表格执行简单插入,只需填充 id_user 名称 ,列 年龄 应该自动生成吗?让我们看......

@asyncio.coroutine
def go():
  engine = yield from create_engine('postgresql://USER@localhost/DB')
  data = {'id_user':1, 'name':'Jimmy' }
  stmt = users.insert(values=data, inline=False)
  with (yield from engine) as conn:
    result = yield from conn.execute(stmt)


loop = asyncio.get_event_loop()
loop.run_until_complete(go())

这是带有相应错误的结果语句:

INSERT INTO users (id_user, name, age) VALUES (1, 'Jimmy', null);

psycopg2.IntegrityError: null value in column "age" violates not-null constraint

我没有提供年龄列,那么 age = null 值来自何处?我期待这样的事情:

INSERT INTO users (id_user, name) VALUES (1, 'Jimmy');

或者 默认 标志实际上应该是:

INSERT INTO users (id_user, name, Age) VALUES (1, 'Jimmy', 0);

你能否对此有所了解?

2 个答案:

答案 0 :(得分:3)

此问题已被确认有 aiopg 错误。似乎目前它忽略了数据操作的default参数。

我已使用server_default修正了此问题:

users = Table('users', metadata,
          Column('id_user', Integer, primary_key=True, nullable=False),
          Column('name', String(20), unique=True),
          Column('age', Integer, nullable=False, server_default='0'))

答案 1 :(得分:0)

我认为您需要在插入中使用inline=True。这将关闭“预执行”。 对于这种“预执行”的含义,文档有点神秘,但他们提到了默认参数:

    :param inline:
      if True, SQL defaults present on :class:`.Column` objects via
      the ``default`` keyword will be compiled 'inline' into the statement
      and not pre-executed.  This means that their values will not
      be available in the dictionary returned from
      :meth:`.ResultProxy.last_updated_params`.

这段docstring来自Update类,但它们与Insert有共同的行为。

此外,这是他们测试它的唯一方法: https://github.com/zzzeek/sqlalchemy/blob/rel_0_9/test/sql/test_insert.py#L385