【问题标题】:Setting SQLAlchemy autoincrement start value设置 SQLAlchemy 自动增量起始值
【发布时间】:2012-05-16 15:59:36
【问题描述】:

SQLAlchemy 中的autoincrement 参数似乎只有TrueFalse,但我想设置预定义值aid = 1001,下一次插入完成时通过自动增量aid = 1002

在 SQL 中,可以这样改变:

ALTER TABLE article AUTO_INCREMENT = 1001;

我正在使用MySQL,我尝试了以下操作,但它不起作用:

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Article(Base):
    __tablename__ = 'article'
    aid = Column(INTEGER(unsigned=True, zerofill=True), 
                autoincrement=1001, primary_key=True)

那么,我怎样才能得到它?提前致谢!

【问题讨论】:

    标签: python sqlalchemy auto-increment


    【解决方案1】:

    根据the docs

    自动增量 - 此标志可以设置为 False 以指示不应被视为“自动增量”列的整数主键列,即在 INSERT 时隐式生成值的整数主键列,其值通常通过 DBAPI 游标返回.lastrowid 属性。它默认为 True 以满足具有单个整数主键列的表的常见用例。

    所以,autoincrement 只是一个标志,让SQLAlchemy 知道它是否是您要递增的主键。

    您要做的是创建一个自定义的自动增量序列

    所以,我认为,您的示例应该类似于:

    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.schema import Sequence
    
    Base = declarative_base()
    
    class Article(Base):
        __tablename__ = 'article'
        aid = Column(INTEGER(unsigned=True, zerofill=True), 
                     Sequence('article_aid_seq', start=1001, increment=1),   
                     primary_key=True)
    

    注意,我不知道您是否使用PostgreSQL,所以如果您使用,请记下following

    Sequence 对象还实现了特殊功能以适应 Postgresql 的 SERIAL 数据类型。 PG 中的 SERIAL 类型会自动生成在插入期间隐式使用的序列。这意味着如果一个 Table 对象在其主键列上定义了一个序列以便它与 Oracle 和 Firebird 一起工作,那么该序列将妨碍 PG 通常使用的“隐式”序列。对于这个用例,将标志 optional=True 添加到 Sequence 对象 - 这表明只有在数据库没有提供其他选项来生成主键标识符时才应该使用 Sequence。

    【讨论】:

    • 我正在使用 MySQL。根据文档:它只对明确支持序列的数据库产生影响,目前包括 PostgresqlOracleFirebird。我试过你的代码,但还是不行。
    • 啊,我的错(只要我能看到,我就使用 PG)。在这种情况下,我会在上面@van 的回答中达到顶峰!
    • 对不起我的英语不好。(我不知道my badtake a peak at的含义)事实上,@van的答案比你的要晚。非常感谢!
    • my bad - 意思是“这是我的错,对不起”。我本来想输入take a peek at,但打错了。它的意思是“去看看”。
    • 这是真正的答案,DDL 是肮脏的做法
    【解决方案2】:

    您可以使用DDLEvents 来实现此目的。这将允许您在 CREATE TABLE 运行之后运行其他 SQL 语句。查看链接中的示例,但我猜您的代码将类似于以下内容:

    from sqlalchemy import event
    from sqlalchemy import DDL
    event.listen(
        Article.__table__,
        "after_create",
        DDL("ALTER TABLE %(table)s AUTO_INCREMENT = 1001;")
    )
    

    【讨论】:

    • 有没有办法根据数据库提供者排除这个执行? ALTER ... AUTO_INCREMENT 适用于 MySQL(以及我认为的大多数其他数据库),但是,SQLITE 显然不支持此 SQL。我能找到的最接近的解决方法是插入/删除:stackoverflow.com/questions/692856/…
    • 回答了我自己的问题。通过代码,我找到了解决方案,记录为:docs.sqlalchemy.org/en/rel_0_8/core/… 以上可以重写为 event.listen( Article.__table__, "after_create", DDL("ALTER TABLE %(table)s AUTO_INCREMENT = 1001; ").execute_if(dialect=('postgresql', 'mysql')) ) 这让我解决了 sqlite 问题。
    【解决方案3】:

    我无法使用 mysql 和 flask-migrate 获得其他答案,因此我在迁移文件中执行了以下操作。

    from app import db
    db.engine.execute("ALTER TABLE myDB.myTable AUTO_INCREMENT = 2000;")
    

    请注意,如果您重新生成迁移文件,这将被覆盖。

    【讨论】:

      【解决方案4】:

      您可以使用mysql_auto_increment 表创建选项来完成。还有mysql_enginemysql_default_charset 选项,可能也很方便:

      article = Table(
          'article', metadata,
          Column('aid', INTEGER(unsigned=True, zerofill=True), primary_key=True),
          mysql_engine='InnoDB',
          mysql_default_charset='utf8',
          mysql_auto_increment='1001',
      )
      

      上面会生成:

      CREATE TABLE article (
          aid INTEGER UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT, 
          PRIMARY KEY (aid)
      )ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8
      

      【讨论】:

        【解决方案5】:

        我知道这是一个老问题,但我最近不得不弄清楚这一点,而且没有一个可用的答案是我所需要的。我找到的解决方案依赖于SQLAlchemy 中的Sequence。无论出于何种原因,当我在上面提到的 Column 构造函数中调用 Sequence 构造函数时,我无法让它工作。作为说明,我使用的是 PostgreSQL。

        对于你的回答,我会这样说:

        from sqlalchemy.ext.declarative import declarative_base
        from sqlalchemy import Sequence, Column, Integer
        
        import os
        from sqlalchemy.ext.declarative import declarative_base
        from sqlalchemy import Column, Sequence, Integer, create_engine
        Base = declarative_base()
        
        def connection():
            engine = create_engine(f"postgresql://postgres:{os.getenv('PGPASSWORD')}@localhost:{os.getenv('PGPORT')}/test")
            return engine
        
        engine = connection()
        
        class Article(Base):
            __tablename__ = 'article'
            seq = Sequence('article_aid_seq', start=1001)
            aid = Column('aid', Integer, seq, server_default=seq.next_value(), primary_key=True)
        
        Base.metadata.create_all(engine)
        

        然后可以在 PostgreSQL 中调用:

        insert into article (aid) values (DEFAULT);
        select * from article;
        
         aid  
        ------
         1001
        (1 row)
        

        希望这对我有所帮助

        【讨论】:

          猜你喜欢
          • 2017-05-20
          • 1970-01-01
          • 2016-05-10
          • 1970-01-01
          • 1970-01-01
          • 2011-11-25
          • 2015-10-30
          • 2017-03-09
          • 1970-01-01
          相关资源
          最近更新 更多