【问题标题】:Using SQLAlchemy ORM for a non-primary key, unique, auto-incrementing id将 SQLAlchemy ORM 用于非主键、唯一、自动递增的 id
【发布时间】:2022-01-12 11:49:41
【问题描述】:

当我运行以下代码时,我希望 first_name 和 last_name 是复合主键,并且 id 是行的自动递增索引,但不充当主键,因为有信息在表的其余部分是我需要定义它的唯一性,而不是给定的 ID。

Base = declarative_base()
Session = sessionmaker(bind=db)
session = Session()

class Person(Base):
    __tablename__ = "people"
    id = Column(Integer, index=True, unique=True, autoincrement=True, primary_key=False)
    first_name = Column(String(30), primary_key=True)
    last_name = Column(String(30), primary_key=True)

if __name__ == "__main__":
    Base.metadata.create_all(db)
    session.add_all([
        Person(first_name="Winston", last_name="Moy"),
        Person(first_name="Bill", last_name="Gates"),
        Person(first_name="Steve", last_name="Jobs"),
        Person(first_name="Quinten", last_name="Coldwater")
    ])
    session.commit()

我在 DataGrip 中查看结果的问题,我得到了下表。数据不是按添加顺序排列的,id 列是空的,而不是我期望的自动递增整数。

要明确:我的问题是:如何为不是主键的 SQLAlchemy ORM 类创建自动递增索引?

【问题讨论】:

  • 如果你不需要递增,你可以使用UUID4s

标签: python mysql sqlalchemy flask-sqlalchemy


【解决方案1】:

在撰写本文时,SQLAlchemy 1.1 不支持在非主键字段上自动递增。

【讨论】:

    【解决方案2】:

    Postgresql 2022 答案:

    以下代码

    import uuid
    from sqlalchemy import Integer, Column, String, Sequence
    from sqlalchemy.dialects.postgresql import UUID
    
    class Test(Base):
        __tablename__ = 'Test'
    
        id_sec = Sequence(__tablename__ + "_id_seq")
        id = Column(Integer, id_sec, server_default=id_sec.next_value(), nullable=False)
        uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    
        # your data
        .... 
    

    生成下表:

                                          Table "public.Test"
        Column     |       Type        | Collation | Nullable |                   Default                    
    ---------------+-------------------+-----------+----------+----------------------------------------------
     id            | integer           |           | not null | nextval('"Test_id_seq"'::regclass)
     uuid          | uuid              |           | not null | 
    

    因此您可以在不指定 id 的情况下插入行

    PostgreSQL 13.5
    SQLAlchemy==1.4.29
    

    【讨论】:

      【解决方案3】:

      mysql 的工作方法:

      sqlalchemy创建表后,
      手动更改表(添加 AUTO_INCREMENT 属性)使用 DDL。
      (在表after_create事件)。

      然后它将像create_all()

      一样按需执行

      测试代码(1.4.x):

      from sqlalchemy.ext.declarative import declarative_base
      
      # --- 1. define table
      base = declarative_base()
      class store(base):
          __tablename__ = 'store'
          id  = Column(Integer,    autoincrement=True, unique=True, primary_key=False) # AI here not work
      
          did = Column(String(64), unique=False, nullable=False)
          fid = Column(String(64), unique=False, nullable=False)
      
          __table_args__ = (
              PrimaryKeyConstraint('did', 'fid', name='idx_did_fid'),
          )
      
      
      print(store)
      
      # --- 2. fix autoincre on non-primary key // will execute as need, like create_all() dose
      from sqlalchemy import event, DDL
      event.listen(
          base.metadata, 'after_create',  DDL('ALTER TABLE `store` CHANGE `id` `id` INT(11) NULL DEFAULT NULL AUTO_INCREMENT')
      )
      
      # --- 3. create table as need
      base.metadata.create_all(engine)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-11
        • 2016-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        相关资源
        最近更新 更多