web2py update_or_insert以递增计数器

时间:2018-04-08 21:09:23

标签: sql-update counter sql-insert web2py

我有一个web2py定义的数据库表,用于计算特定用户发出请求的次数 - 因此它有整数列' user_id'和' n_req'。我不想为每个可能的用户填充零。相反,我想检查是否存在具有user_id的行,如果存在,则递增' n_req'一个,否则创建一个初始值为'n_req'为了避免竞争条件,我想使用单个update_or_insert调用来执行此操作,例如

db.count_table.update(db.count_table.user_id == uid, user_id = uid, n_req = n_req + 1)

我认为我不能这样做,因为它在递增时使用预先存在的n_req值。那么如何告诉DAL n_req的初始值。我可以这样做,例如,n_req = (n_req || 0) + 1

1 个答案:

答案 0 :(得分:1)

在这种情况下,我认为您无法使用.update_or_insert方法,因为n_rec的值取决于是否找到记录。相反,你可以做这样的事情:

db.define_table('count_table',
    Field('user_id', 'integer', unique=True),
    Field('n_rec', 'integer', default=1))

def update_count(user_id):
    return db(db.count_table.user_id == user_id).update(n_rec=db.count_table.n_rec + 1)

if not update_count(uid):
    try:
        db.count_table.insert(user_id=uid)
    except db._adapter.driver.IntegrityError:
        update_count(uid)

请注意n_rec.update的值设置为db.count_table.n_rec + 1,这将转换为SQL语句,该语句将使数据库增加现有值,而不是显式提供最终值重视自己。如果两个请求同时更新计数,这应避免竞争条件。

另请注意,unique字段存在user_id约束。这将防止竞争条件允许为同一用户创建两个记录。在这种情况下,try/except将捕获生成的IntegrityError,并且将对现有记录进行更新。