Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SQL Alchemy默认值函数,用于在唯一的父子记录组中模拟自动递增_Python_Sqlalchemy_Primary Key_Auto Increment_Declarative - Fatal编程技术网

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

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

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

我使用的是声明性基本方法

我使用FKs和relation函数设置父子关系。我试图实现的是获得一个类似于伪自动递增函数的函数,它将查找Category unique name组中的max CategoryID值,并将其递增1。我尝试过使用各种默认函数,但遇到的问题是无法在插入时指定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炼金术中实现这一点的一些指导。我知道我总是可以查找该值并直接在同一事务中指定它,但我正在尝试提出一种独立的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()
    ,并使用触发器在服务器端执行作业
  • 所有这些解都具有ddaa提到的竞争条件。在竞争条件下,您的代码不会破坏数据库状态,但在正确定义主键时会异常失败(对于您的代码来说不是这样!)。在某些罕见的情况下,某些应用程序失败(在web应用程序中显示500页)是可以接受的


    请注意,您已将
    类别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值的现有逻辑。我不反对,但我想避免。对不起。我不熟悉堆栈溢出。刚刚接受了你上面的答案。