主要ID序列不递增

时间:2017-05-26 05:15:34

标签: python postgresql sqlalchemy sequence auto-increment

我有一个像这样设置的表:

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序列自动增量

1 个答案:

答案 0 :(得分:2)

问题是当前版本的Table对象定义为我们提供了下一个CREATE TABLE语句

CREATE TABLE users (
    id INTEGER NOT NULL, 
    first_name VARCHAR(255), 
    last_name VARCHAR(255), 
    PRIMARY KEY (id)
)

虽然它可能应该是

  1. CREATE TABLE users (
        id INTEGER DEFAULT nextval('user_id_seq') NOT NULL, 
        first_name VARCHAR(255), 
        last_name VARCHAR(255), 
        PRIMARY KEY (id)
    )
    
  2. 或只是这个

    CREATE TABLE users (
        id SERIAL NOT NULL, 
        first_name VARCHAR(255), 
        last_name VARCHAR(255), 
        PRIMARY KEY (id)
    )
    
  3. 因此对于每个声明解决方案都是:

    1. 关注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')
      
    2. 如果使用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')
      
    3. 我更喜欢第二个,因为使用Sequence看起来像YAGNI

      P上。 S上。

      为什么你顺便使用UPPER_CASE' d名字?这些对象对我来说不像constants,因为你可以自由地mutate PEP-8