Python SQL Alchemy默认值函数,用于在唯一的父子记录组中模拟自动递增
我有一个小问题,我认为SQL炼金术应该可以很容易地解决,但我似乎无法正确处理它。我有两个表,一个是父表,另一个是子表。对于每个子记录,它都需要一个唯一的ID,但仅限于唯一父记录的上下文 我使用的是声明性基本方法 我使用FKs和relation函数设置父子关系。我试图实现的是获得一个类似于伪自动递增函数的函数,它将查找Category unique name组中的max CategoryID值,并将其递增1。我尝试过使用各种默认函数,但遇到的问题是无法在插入时指定CategoryUniqueName。我找不到传递CategoryItems.CategoryUniqueName的当前值的方法,以便在尝试选择func.max(CategoryItems.CategoryID)之类的内容时,查找查询应用了正确的筛选器。如果我硬编码一个查询,它工作得很好。这是我认为应该起作用的方法,但是,再一次,我找不到为过滤器指定唯一值的方法Python SQL Alchemy默认值函数,用于在唯一的父子记录组中模拟自动递增,python,sqlalchemy,primary-key,auto-increment,declarative,Python,Sqlalchemy,Primary Key,Auto Increment,Declarative,我有一个小问题,我认为SQL炼金术应该可以很容易地解决,但我似乎无法正确处理它。我有两个表,一个是父表,另一个是子表。对于每个子记录,它都需要一个唯一的ID,但仅限于唯一父记录的上下文 我使用的是声明性基本方法 我使用FKs和relation函数设置父子关系。我试图实现的是获得一个类似于伪自动递增函数的函数,它将查找Category unique name组中的max CategoryID值,并将其递增1。我尝试过使用各种默认函数,但遇到的问题是无法在插入时指定CategoryUniqueNam
unique_group='my_group'
result=con.query(func.max(CategoryItems.CategoryID)).filter(and_(
CategoryItems.CategoryUniqueName==unique_group,
)).one()
课程如下所示。非常感谢关于如何在标准SQL炼金术中实现这一点的一些指导。我知道我总是可以查找该值并直接在同一事务中指定它,但我正在尝试提出一种独立的SQL炼金术方法,它不需要其他地方的额外逻辑
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"
))
那么,您试图实现的是让每一组具有不同CategoryUniqueName的CategoryItem分别自动递增它们的CategoryId 如果这是正确的,那么您当前的方法(获取要添加到的CategoryItems子集中CategoryId的当前最大值)将被破坏。它有一个内在的竞争条件:并发插入将使用相同的CategoryId 您真的需要单独增加您的CategoryId吗?为什么不直接使用普通的自动递增功能呢。给定CategoryUniqueName的序列CategoryId将有洞,但这真的是个问题吗 如果您需要连续的序列号,则需要使用一些手动锁定来防止竞争状况。我认为有3种方法可以做到:
创建映射程序扩展名钩子替换插入的参数
上下文
参数调用此函数,该参数包含所需的所有数据:上下文。已编译的_参数[0]['CategoryUniqueName']
,上下文。连接
server\u default
参数中传递FetchedValue()
,并使用触发器在服务器端执行作业请注意,您已将
类别ID
定义为主键。这将不允许对CategoryUniqueName
列的不同值重复使用相同的数字。您必须将其更改为2列的复合主索引。感谢您的洞察力Denis,您已经做到了。我使用了选项1和选项2,它们工作得非常好。上下文参数是选项2的关键。我没有意识到它是自动通过的。我注意到的一件事是,选项1将引入竞争条件,即使在单用户提交多条记录的情况下也是如此。我认为这与冲水和节省时间有关。然而,选项2的工作非常出色
这是现在从默认参数调用的小函数:
def getNextId(context):
unique_name=context.compiled_parameters[0]['CategoryUniqueName']
sql = """
SELECT MAX(CategoryID)
FROM child_table
WHERE CategoryUniqueName='%s'""" % (unique_name, )
result = context.connection.execute(sql).fetchone()[0]
if result > 0:
return result + 1
else:
return 1
我明白你对比赛条件的看法。如果我可以锁定事务以防止竞争条件,是否有方法将CategoryItems.CategoryUniqueName的当前值传递到函数中?我认为在插入之前将当前字段值传递到函数中的能力对于其他事情(如基于字段生成哈希)是有益的。为了回答全局自动增量方法的问题…是的,我可以改为这样,但需要一些非常重要的工作来处理基于当前CategoryID值的现有逻辑。我不反对,但我想避免。对不起。我不熟悉堆栈溢出。刚刚接受了你上面的答案。