我有一个像这样设置的表:
USERS_TABLE = \
Table("users", META_DATA,
Column("id", Integer, Sequence("user_id_seq"), primary_key=True),
Column("first_name", String(255)),
Column("last_name", String(255))
)
我能够像这样插入单行:
INS_EXPRESSION = insert(USERS_TABLE)
SEQ = Sequence('user_id_seq')
INS_EXPRESSION.values(first_name="Foo", last_name="Bar")
但是,如果我尝试第二次插入,我会收到此错误:
sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) null value in column "id" violates not-null constraint
DETAIL: Failing row contains (null, null, null).
[SQL: 'INSERT INTO users DEFAULT VALUES']
如何使user_id_seq
序列自动增量?
答案 0 :(得分:2)
问题是当前版本的Table
对象定义为我们提供了下一个CREATE TABLE
语句
CREATE TABLE users (
id INTEGER NOT NULL,
first_name VARCHAR(255),
last_name VARCHAR(255),
PRIMARY KEY (id)
)
虽然它可能应该是
此
CREATE TABLE users (
id INTEGER DEFAULT nextval('user_id_seq') NOT NULL,
first_name VARCHAR(255),
last_name VARCHAR(255),
PRIMARY KEY (id)
)
或只是这个
CREATE TABLE users (
id SERIAL NOT NULL,
first_name VARCHAR(255),
last_name VARCHAR(255),
PRIMARY KEY (id)
)
因此对于每个声明解决方案都是:
关注this recipe我们可以设置server_default
来排序' nextval
from sqlalchemy import (MetaData, Table, Column,
Integer, String, Sequence,
create_engine,
insert)
db_uri = 'postgresql://username:password@hostname:5432/database'
engine = create_engine(db_uri)
META_DATA = MetaData(bind=engine)
user_id_seq = Sequence("user_id_seq", metadata=META_DATA)
USERS_TABLE = Table("users", META_DATA,
Column("id", Integer, user_id_seq,
server_default=user_id_seq.next_value(),
primary_key=True),
Column("first_name", String(255)),
Column("last_name", String(255)))
USERS_TABLE.create(checkfirst=True)
INS_EXPRESSION = insert(USERS_TABLE).values(first_name="Foo", last_name="Bar")
engine.execute(INS_EXPRESSION)
engine.execute('INSERT INTO users DEFAULT VALUES')
如果使用Sequence
并不重要,我们可以删除它,只需将autoincrement
标记设置为True
(它也可以在不设置的情况下删除Sequence
国旗because
... SQLAlchemy会自动将第一个未标记为FK的Integer PK列设置为
autoincrement=True
...
但它会更好,因为它更多explicit):
from sqlalchemy import MetaData, Table, Column, Integer, String, create_engine, insert
db_uri = 'postgresql://username:password@hostname:5432/database'
engine = create_engine(db_uri)
META_DATA = MetaData(bind=engine)
USERS_TABLE = Table("users", META_DATA,
Column("id", Integer,
autoincrement=True,
primary_key=True),
Column("first_name", String(255)),
Column("last_name", String(255)))
USERS_TABLE.create(checkfirst=True)
INS_EXPRESSION = insert(USERS_TABLE).values(first_name="Foo", last_name="Bar")
engine.execute(INS_EXPRESSION)
engine.execute('INSERT INTO users DEFAULT VALUES')
我更喜欢第二个,因为使用Sequence
看起来像YAGNI。
为什么你顺便使用UPPER_CASE' d名字?这些对象对我来说不像constants,因为你可以自由地mutate PEP-8)