我有一个小问题,我认为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}$
我认为有三条路可以走:
before_insert()
钩子替换插入的参数创建映射器扩展。在default
参数传递。此函数使用context
参数调用,其中包含您需要的所有数据:context.compiled_parameters[0]['CategoryUniqueName']
,context.connection
。在server_default
参数中传递FetchedValue()
,并使用触发器执行服务器端的作业。在所有这些解都有ddaa提到的竞争条件。在竞争条件的情况下,您的代码不会破坏数据库状态,但在正确定义主键时将异常失败(对于您的代码来说,这不是真的!)。在某些罕见的情况下,某些应用程序失败(在web应用程序中显示500页)可能是可以接受的。在
注意,您已经将
CategoryID
定义为主键。这将不允许对CategoryUniqueName
列的不同值重用相同的数字。必须将其更改为2列的复合主索引。在所以,您要实现的是让每个具有不同CategoryUniqueName的categoryItem集合分别自动递增它们的CategoryId?在
如果这是正确的,那么您当前的方法(获取要添加到的CategoryItems子集中CategoryId的当前最大值)就被破坏了。它有一个内在的竞争条件:并发插入将使用相同的CategoryId。在
你真的需要你的CategoryId单独递增吗?为什么不直接使用普通的自动递增功能呢。给定CategoryUniqueName的序列CategoryId会有漏洞,但这真的是个问题吗?在
如果需要连续的序列号,则需要使用一些手动锁定来防止争用情况。在
谢谢你的洞察力丹尼斯,你很准确。我玩了两个选项1和2,他们工作得很好。上下文参数是选项2的键。我没意识到它是自动通过的。我注意到的一件事是,选项1将引入一个竞争条件,即使在单个用户提交多个记录的上下文中也是如此。我想这跟冲水和节省时间有关。然而,方案2的工作非常出色。在
这是从默认参数调用的小函数:
相关问题 更多 >
编程相关推荐