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

2024-09-28 05:16:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个小问题,我认为SQL炼金术应该很容易处理,但我似乎无法正确处理它。我有两个表,一个是父表,另一个是子表。对于每个子记录,它需要一个唯一的ID,但仅限于唯一父记录的上下文。在

我使用的是声明式的基本方法。在

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

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

课程如下所示。非常感谢有关如何在标准SQL炼金术中实现这一点的指导。我知道我总是可以查找值并在同一个事务中直接指定它,但我正试图想出一种独立的SQL炼金术方法,它不需要其他地方的额外逻辑。在

^{pr2}$

Tags: 方法函数idsql记录groupmax正确处理
3条回答

我认为有三条路可以走:

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

所有这些解都有ddaa提到的竞争条件。在竞争条件的情况下,您的代码不会破坏数据库状态,但在正确定义主键时将异常失败(对于您的代码来说,这不是真的!)。在某些罕见的情况下,某些应用程序失败(在web应用程序中显示500页)可能是可以接受的。在

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

所以,您要实现的是让每个具有不同CategoryUniqueName的categoryItem集合分别自动递增它们的CategoryId?在

如果这是正确的,那么您当前的方法(获取要添加到的CategoryItems子集中CategoryId的当前最大值)就被破坏了。它有一个内在的竞争条件:并发插入将使用相同的CategoryId。在

你真的需要你的CategoryId单独递增吗?为什么不直接使用普通的自动递增功能呢。给定CategoryUniqueName的序列CategoryId会有漏洞,但这真的是个问题吗?在

如果需要连续的序列号,则需要使用一些手动锁定来防止争用情况。在

谢谢你的洞察力丹尼斯,你很准确。我玩了两个选项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 

相关问题 更多 >

    热门问题