40 lines
1.3 KiB
Python
40 lines
1.3 KiB
Python
"""领取用的分段 UPDATE。
|
||
|
||
每段 500 个 fid,避开 Oracle 一条 IN 最多 1000 个表达式。
|
||
调用方持有事务:本模块不提交。任一段失败由调用方整笔回滚。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
FID_CHUNK_SIZE = 500
|
||
|
||
|
||
def update_by_fid_chunks(
|
||
cur,
|
||
sql_template: str,
|
||
fids: list[int],
|
||
binds: dict | None = None,
|
||
) -> None:
|
||
"""按每段 500 个 fid 执行同一条 UPDATE。
|
||
|
||
sql_template 用 {placeholders} 放本段占位符。各段在当前游标上顺序执行,不提交。
|
||
空列表不执行。任一段抛错时前面各段已执行但未提交,调用方应整笔回滚。
|
||
"""
|
||
if not fids:
|
||
return
|
||
extra = dict(binds or {})
|
||
for start in range(0, len(fids), FID_CHUNK_SIZE):
|
||
chunk = list(fids[start : start + FID_CHUNK_SIZE])
|
||
placeholders, fid_binds = _fid_placeholders(chunk)
|
||
cur.execute(
|
||
sql_template.format(placeholders=placeholders),
|
||
{**extra, **fid_binds},
|
||
)
|
||
|
||
|
||
def _fid_placeholders(fids: list[int]) -> tuple[str, dict[str, int]]:
|
||
"""把本段 fid 编成 :id0, :id1 占位和 bind。段内从 0 编号。"""
|
||
fid_binds = {f"id{index}": value for index, value in enumerate(fids)}
|
||
placeholders = ", ".join(f":id{index}" for index in range(len(fids)))
|
||
return placeholders, fid_binds
|