python - SQL Alchemy 默认值函数,用于在唯一的父子记录组中模拟自动增量

标签 python sqlalchemy primary-key auto-increment declarative

我有一个小问题,我认为应该可以通过 SQL Alchemy 轻松解决,但我似乎无法解决。我有两张表,一张是父表,另一张是子表。对于每个子记录,它需要一个唯一的 ID,但只需要具有唯一父记录的上下文。

我正在使用声明性基础方法。

我使用 FK 和关系函数设置父子关系。我想要实现的是获得类似于伪自动增量函数的东西,该函数将查找类别唯一名称组中的最大类别 ID 值并将其递增一个。我试过使用各种默认函数,但我遇到的问题是无法在插入时指定 CategoryUniqueName。我找不到一种方法来传递 CategoryItems.CategoryUniqueName 的当前值,以便在尝试选择 func.max(CategoryItems.CategoryID) 之类的内容时查找查询应用正确的过滤器。如果我对查询进行硬编码,它就可以正常工作。这就是我认为应该起作用的方法,但同样,我找不到为过滤器指定唯一值的方法。

unique_group='my_group'
result=con.query(func.max(CategoryItems.CategoryID)).filter(and_(
        CategoryItems.CategoryUniqueName==unique_group, 
    )).one()

类如下所示。非常感谢有关如何在标准 SQL Alchemy 中完成此操作的一些指导。我知道我总是可以查找值并直接在同一事务中直接指定它,但我正在尝试提出一种不需要其他地方额外逻辑的独立 SQL Alchemy 方法。

class Category(Base):
    __tablename__ = 'parent_table'
    __table_args__ = {'mysql_engine':'InnoDB', 'useexisting':True}

    CategoryUniqueName = Column(Unicode(255), primary_key=True)
    CategoryGroupName = Column(Unicode(255), nullable=False)
    CategoryGroupMemo = Column(UnicodeText)
    SortOrder = Column(Integer, index=True)
    IsLocked = Column(Boolean, default=0)

class CategoryItems(Base):
    __tablename__ = 'child_table'
    __table_args__ = {'mysql_engine':'InnoDB', 'useexisting':True}

    CategoryUniqueName = Column(Unicode(255), ForeignKey(Category.CategoryUniqueName), primary_key=True)
    CategoryID = Column(Integer, primary_key=True, autoincrement=False)
    CategoryName = Column(Unicode(255), nullable=False, index=True)
    CategoryMemo = Column(UnicodeText)
    CategoryImage = Column(Unicode(255))
    CategoryFlex1 = Column(Unicode(255), index=True)
    CategoryFlex2 = Column(Unicode(255), index=True)
    CategoryFlex3 = Column(Unicode(255), index=True)
    SortOrder = Column(Integer, index=True)

    category_group = relation(
        Category, 
        backref=backref(
            'items', 
            order_by=SortOrder, 
            collection_class=ordering_list('SortOrder'), 
            cascade="all, delete, delete-orphan"
    ))

最佳答案

我看到了 3 种方法:

  1. 最明显且有据可查的。使用 before_insert() Hook 替换插入的参数创建映射器扩展。
  2. 将函数作为默认 参数传递。此函数使用 context 参数调用,其中包含您需要的所有数据:context.compiled_pa​​rameters[0]['CategoryUniqueName']context.connection
  3. server_default 参数中传递 FetchedValue() 并使用触发器在服务器端执行作业。

所有这些解决方案都具有 ddaa 提到的竞争条件。在竞争条件的情况下,您的代码不会破坏数据库状态,但是当主键定义正确时会失败并出现异常(您的代码不是这样!)。在极少数情况下,某些应用程序失败(在 Web 应用程序中显示 500 页)可能是可以接受的。

请注意,您已将 CategoryID 定义为主键。这将不允许为 CategoryUniqueName 列的不同值重复使用相同的数字。您必须将其更改为 2 列的复合主索引。

关于python - SQL Alchemy 默认值函数,用于在唯一的父子记录组中模拟自动增量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1870364/

相关文章:

database - 卡宴,Postgres : primary key generation

python - 添加requirements.txt [Python]时数据流失败

python - 如何以字符串格式编写多行函数?

python - 使用 SQLAlchemy 继承参数的 SQLite 和 Postgres 部分索引支持

python - 在sqlalchemy中过滤或过滤多个

Hibernate/JPA 2/PostgreSQL - 实体 UUID 作为主键

php - Mysql autoincrement id or alphanumeric id 作为外键

python - FileNotFoundError : [Errno 2] No such file or directory

python - 使用更改指示器拆分字符串 python

python - SQLAlchemy 过滤器用于不包含数组列中值的行