From f01e772b06ef9049d2f1204ac1f120dff4e0f0c5 Mon Sep 17 00:00:00 2001 From: wintsa Date: Fri, 27 Jun 2025 16:35:46 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E6=88=90=E5=94=AF=E4=B8=80=E7=BC=96?= =?UTF-8?q?=E5=8F=B7(=E9=98=B2=E6=AD=A2=E9=AB=98=E5=B9=B6=E5=8F=91?= =?UTF-8?q?=E9=87=8D=E5=A4=8D).sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 生成唯一编号(防止高并发重复),并且有demo,示范如何批量更新历史数据的编号 --- 生成唯一编号(防止高并发重复).sql | 111 +++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 生成唯一编号(防止高并发重复).sql diff --git a/生成唯一编号(防止高并发重复).sql b/生成唯一编号(防止高并发重复).sql new file mode 100644 index 0000000..44b48a5 --- /dev/null +++ b/生成唯一编号(防止高并发重复).sql @@ -0,0 +1,111 @@ +call SP_GENERATE_FORMATTED_SEQUENCE( 'JSXMlxdj' --key,同一个模块同一个流程必须唯一 , + '{?REQUESTID}' --传值 , + '{?sqrq}' --日期传值,默认传2025-02-11字符串格式, + 'formtable_main_1576' --需要被update的表单名称 , + 'jsxmbh' --需要被update的字段名称 , + 'requestid' --被update的where条件的字段名, + '#P-#Y-#S4' --编号排列,#S4代表补位4个,比如0014。排列也可以是'[#p-#Y]/#S',输出结果是[JSXM-2025]/1, + 'JSXM' --这个就是上面的#p ) + + +--批量更新历史表单的编号 +DECLARE + v_count NUMBER := 0; + v_error_count NUMBER := 0; + v_total_count NUMBER := 0; + + -- 游标:获取所有需要更新的记录(按ID排序) + CURSOR c_records IS + SELECT xglc, djrq + FROM uf_gcxx + WHERE xglc IS not NULL -- 只更新空编号的记录 + ORDER BY xglc; -- 按ID排序 + +BEGIN + -- 统计总记录数 + SELECT COUNT(*) INTO v_total_count + FROM uf_gcxx + WHERE xglc IS not NULL; + + DBMS_OUTPUT.PUT_LINE('开始批量更新历史数据...'); + DBMS_OUTPUT.PUT_LINE('需要更新的记录总数: ' || v_total_count); + DBMS_OUTPUT.PUT_LINE('----------------------------------------'); + + -- 遍历每条记录 + FOR rec IN c_records LOOP + BEGIN + -- 调用存储过程为每条记录生成编号 + SP_GENERATE_FORMATTED_SEQUENCE( + 'JSXMlxdj', -- 序列键 + rec.xglc, -- 请求ID/记录ID + rec.djrq, -- 日期值 + 'uf_gcxx', -- 目标表名 + 'gcbhz', -- 目标字段名 + 'xglc', -- 记录ID字段名 + '#P-#Y-#S4', -- 编号格式模式 + 'JSXM' -- 前缀 + ); + + v_count := v_count + 1; + + -- 每处理100条记录显示一次进度 + IF MOD(v_count, 100) = 0 THEN + DBMS_OUTPUT.PUT_LINE('已处理: ' || v_count || '/' || v_total_count || ' 条记录'); + END IF; + + EXCEPTION + WHEN OTHERS THEN + v_error_count := v_error_count + 1; + DBMS_OUTPUT.PUT_LINE('处理记录失败 - ID: ' || rec.xglc || ', 日期: ' || rec.djrq || ', 错误: ' || SQLERRM); + + -- 如果错误太多,停止处理 + IF v_error_count > 50 THEN + DBMS_OUTPUT.PUT_LINE('错误过多,停止处理'); + EXIT; + END IF; + END; + END LOOP; + + DBMS_OUTPUT.PUT_LINE('----------------------------------------'); + DBMS_OUTPUT.PUT_LINE('批量更新完成!'); + DBMS_OUTPUT.PUT_LINE('成功更新: ' || v_count || ' 条记录'); + DBMS_OUTPUT.PUT_LINE('失败记录: ' || v_error_count || ' 条记录'); + + -- 验证更新结果 + DECLARE + v_updated_count NUMBER; + v_empty_count NUMBER; + BEGIN + SELECT COUNT(*) INTO v_updated_count + FROM uf_gcxx + WHERE gcbhz IS NOT NULL AND gcbhz != ''; + + SELECT COUNT(*) INTO v_empty_count + FROM uf_gcxx + WHERE gcbhz IS NULL OR gcbhz = ''; + + DBMS_OUTPUT.PUT_LINE('----------------------------------------'); + DBMS_OUTPUT.PUT_LINE('验证结果:'); + DBMS_OUTPUT.PUT_LINE('已有编号的记录: ' || v_updated_count); + DBMS_OUTPUT.PUT_LINE('仍为空编号的记录: ' || v_empty_count); + END; + +EXCEPTION + WHEN OTHERS THEN + DBMS_OUTPUT.PUT_LINE('批量更新过程出错: ' || SQLERRM); + ROLLBACK; +END; + + +--更新模块后使用update同步到流程表单 +UPDATE formtable_main_1576 a +SET jsxmbh = ( + SELECT gcbhz + FROM uf_gcxx + WHERE xglc = a.requestid +) +WHERE EXISTS ( + SELECT 1 + FROM uf_gcxx + WHERE xglc = a.requestid +);