我在SQLAlchemy中发现了一个意外的行为。我使用以下版本:
这是示例的表定义:
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);
你能否对此有所了解?
答案 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