1. Oracle 存储过程到底能解决什么问题Oracle 存储过程Stored Procedure是一组预编译后存放在数据库里的 PL/SQL 代码块调用一次就能完成一整套逻辑。它最直接的价值是把「循环遍历数据、条件分支判断、游标逐行处理」这三件事从应用层搬到数据库层减少网络往返也避免把大批量数据拉到 Java/Python 里再处理。适合谁需要做批量数据清洗、跨表同步、定时任务、报表预聚合的数据库开发者尤其是手上有一堆tmp_临时表要往正式表搬的场景。我见过太多人写存储过程卡在三个地方循环写不对导致死循环、判断分支漏了ELSE导致空值、游标忘了关或者%NOTFOUND判断位置错了。这篇就把 LOOP/WHILE/FOR 三种循环、IF/CASE 两种判断、显式游标的完整写法串起来给一个能直接复制运行的骨架。同时补上 TaoToken 的统一 Key/API 通道配置让你在写 SQL 的同时把模型调用也收敛到一套配置里不用每个工具单独填 Key。核心检索词先摆出来Oracle 存储过程、循环语句、判断语句、游标。下面所有代码都在 Oracle 11g/19c 的 SQL*Plus 或 SQL Developer 里验证过你可以直接贴进去跑。2. TaoToken 前置统一 Key 与 API 通道准备写存储过程本身不需要联网但你在开发过程中大概率会用到 AI 辅助生成 SQL、解释报错、补全游标逻辑。TaoToken 在这里的作用是提供一个统一的 API 入口把模型对话、编码计划、控制台管理收敛到一套 Key 上省得在多个工具之间来回切换配置。你需要先拿到一个 API Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台里创建 Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。API 基础地址统一用 https://taotoken.net/api 注意这个地址不带 UTM 参数配置时直接写死。如果你只是想让 AI 帮你解释一段游标代码用模型对话页就够了https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果你要长期做数据库开发、写大量 PL/SQL建议看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 它更适合持续性的编码任务。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Claude Code 相关配置参考 https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注意TaoToken 是合规的 API 聚合通道配置时只填官方给的地址不要自行拼接其他域名。3. 可复制配置settings.json 与 config.toml 骨架在动手写存储过程之前先把 AI 辅助工具的配置落地。这样你遇到ORA-06550之类的编译错误时可以直接把报错贴给模型让它结合你的游标代码给出修改建议。3.1 settings.json 配置适用于多数编辑器插件{ ai.provider: taotoken, ai.apiKey: sk-你的TaoTokenKey, ai.baseUrl: https://taotoken.net/api, ai.model: claude-sonnet, ai.timeout: 60000, ai.maxTokens: 4096 }把sk-你的TaoTokenKey替换成你在控制台创建的真实 Key。baseUrl必须写https://taotoken.net/api不要加斜杠结尾也不要带任何查询参数。3.2 config.toml 配置适用于命令行工具[ai] provider taotoken api_key sk-你的TaoTokenKey base_url https://taotoken.net/api model claude-sonnet timeout 60 max_tokens 4096 [ai.retry] max_attempts 3 backoff_ms 1000两个配置文件选一个用就行取决于你的工具链。配好之后你在写存储过程时可以让 AI 直接读取当前文件上下文解释EXIT WHEN和%NOTFOUND的执行顺序。3.3 存储过程完整骨架下面这个存储过程把循环、判断、游标三样东西全用上了。场景是从tmp_fetch_data临时表里取出所有非空的code逐个判断是否已存在于res_netnode不存在就插入。CREATE OR REPLACE PROCEDURE SYNC_NETNODE_DATA IS -- 游标定义取出所有非空 code CURSOR cur_netnode IS SELECT DISTINCT code FROM tmp_fetch_data t WHERE code IS NOT NULL; v_code_src tmp_fetch_data.code%TYPE; v_flag_prv NUMBER; v_type VARCHAR2(10); BEGIN -- 打开游标 OPEN cur_netnode; LOOP -- 抓取一行 FETCH cur_netnode INTO v_code_src; -- 抓不到就退出 EXIT WHEN cur_netnode%NOTFOUND; -- 判断语句根据 code 前缀决定 type IF v_code_src LIKE A% THEN v_type : 1; ELSIF v_code_src LIKE B% THEN v_type : 2; ELSE v_type : 9; END IF; -- 查重 SELECT COUNT(1) INTO v_flag_prv FROM res_netnode WHERE nodename v_code_src; -- 不存在则插入 IF v_flag_prv 0 THEN INSERT INTO res_netnode(nodeid, nodename, upnodeid, type, maxsub, status, memo) VALUES (seq_res_netnode_id.nextval, v_code_src, 0, v_type, 0, 1, NULL); END IF; END LOOP; -- 关闭游标 CLOSE cur_netnode; COMMIT; EXCEPTION WHEN OTHERS THEN IF cur_netnode%ISOPEN THEN CLOSE cur_netnode; END IF; ROLLBACK; RAISE; END SYNC_NETNODE_DATA; /这段代码里有几个关键点。%TYPE让变量类型自动跟随表字段改表结构时不用改存储过程。EXIT WHEN cur_netnode%NOTFOUND必须放在FETCH之后否则第一次循环就会误判。异常块里先判断游标是否还开着再关避免ORA-01001无效游标错误。4. 循环语句三种写法与验证4.1 LOOP 简单循环LOOP ... EXIT WHEN ... END LOOP是最基础的循环适合不知道循环次数、靠条件退出的场景。DECLARE int NUMBER(2) : 0; BEGIN LOOP int : int 1; DBMS_OUTPUT.PUT_LINE(int 的当前值为: || int); EXIT WHEN int 10; END LOOP; END; /执行后输出 1 到 10。注意EXIT WHEN放在自增之后如果放在之前输出会变成 0 到 9。4.2 WHILE 循环WHILE 布尔表达式 LOOP ... END LOOP在每次循环开始前判断条件条件为假直接不进循环。DECLARE x NUMBER : 1; BEGIN WHILE x 10 LOOP DBMS_OUTPUT.PUT_LINE(X的当前值为: || x); x : x 1; END LOOP; END; /WHILE 和 LOOP 的区别WHILE 可能一次都不执行LOOP 至少执行一次。如果你要遍历一个可能为空的集合用 WHILE 更安全。4.3 FOR 循环FOR 计数器 IN [REVERSE] 下限..上限 LOOP ... END LOOP最省心计数器自动声明、自动递增不用手动初始化。BEGIN FOR int IN 1..10 LOOP DBMS_OUTPUT.PUT_LINE(int 的当前值为: || int); END LOOP; END; /加REVERSE就从大到小BEGIN FOR int IN REVERSE 1..10 LOOP DBMS_OUTPUT.PUT_LINE(倒序 int: || int); END LOOP; END; /注意REVERSE后面的数字必须从小到大写REVERSE 10..1是错的会直接编译报错。上下限也不能是变量或表达式只能是整数常量。4.4 验证循环结果在 SQL*Plus 里执行前先开输出SET SERVEROUTPUT ON;然后执行上面的匿名块看到 1 到 10 依次打印就说明循环逻辑通了。如果什么都没输出检查SET SERVEROUTPUT ON有没有执行或者你的客户端是不是把 DBMS_OUTPUT 缓冲区关掉了。5. 判断语句与游标组合实战5.1 IF/ELSIF/ELSE 判断DECLARE x VARCHAR2(10) : 住宅; t NUMBER; BEGIN IF x 住宅 THEN t : 0; ELSIF x 商务 THEN t : 2; ELSIF x 商住 THEN t : 3; ELSE t : 9; END IF; DBMS_OUTPUT.PUT_LINE(t || t); END; /ELSIF不是ELSEIF少一个 E写错直接编译不过。每个分支的THEN不能省。ELSE分支建议永远写上处理意外值避免变量保持 NULL。5.2 CASE 判断CASE 在分支多的时候比 IF 清爽DECLARE x VARCHAR2(10) : 商住; t NUMBER; BEGIN t : CASE x WHEN 住宅 THEN 0 WHEN 商务 THEN 2 WHEN 商住 THEN 3 ELSE 9 END; DBMS_OUTPUT.PUT_LINE(CASE t || t); END; /CASE 是表达式可以直接赋值IF 是语句只能控制流程。需要返回值时优先用 CASE。5.3 显式游标 LOOP FETCH 写法DECLARE CURSOR cur_netnode IS SELECT DISTINCT code FROM tmp_fetch_data t WHERE code IS NOT NULL; v_code_src tmp_fetch_data.code%TYPE; v_flag_prv NUMBER; BEGIN OPEN cur_netnode; LOOP FETCH cur_netnode INTO v_code_src; EXIT WHEN cur_netnode%NOTFOUND; SELECT COUNT(1) INTO v_flag_prv FROM res_netnode WHERE nodename v_code_src; IF v_flag_prv 0 THEN INSERT INTO res_netnode(nodeid, nodename, upnodeid, type, maxsub, status, memo) VALUES (seq_res_netnode_id.nextval, v_code_src, 0, 1, 0, 1, NULL); END IF; END LOOP; CLOSE cur_netnode; COMMIT; END; /5.4 游标 FOR 循环写法FOR 循环处理游标更简洁不用手动 OPEN/FETCH/CLOSEDECLARE CURSOR c_list IS SELECT * FROM table_user i WHERE i.id 4; BEGIN FOR c IN c_list LOOP DBMS_OUTPUT.PUT_LINE(用户的id || c.id); END LOOP; END; /c是隐式声明的记录变量直接c.id就能取字段。循环结束自动关游标异常时也自动关。日常开发我优先用这种写法少写三行代码少三个出错点。5.5 编译与执行验证编译存储过程CREATE OR REPLACE PROCEDURE SYNC_NETNODE_DATA IS ... END SYNC_NETNODE_DATA; /如果编译报错查错误信息SHOW ERRORS PROCEDURE SYNC_NETNODE_DATA;执行BEGIN SYNC_NETNODE_DATA; END; /验证结果SELECT COUNT(1) FROM res_netnode WHERE nodename IN ( SELECT DISTINCT code FROM tmp_fetch_data WHERE code IS NOT NULL );这个数字应该等于tmp_fetch_data里非空 code 的去重数量。如果对不上检查游标 WHERE 条件是不是漏了或者插入时被唯一约束挡了。6. 本篇常见错误排查6.1 ORA-06550 / PLS-00103 编译错误最常见的原因是ELSIF写成ELSEIF或者END LOOP后面漏了分号。用SHOW ERRORS看具体行号PL/SQL 的报错行号有时会偏移一行往上看一行通常能找到问题。6.2 ORA-01001 无效游标在CLOSE之后又FETCH或者异常块里重复关闭。解决办法是在异常处理里加IF cur_netnode%ISOPEN THEN CLOSE cur_netnode; END IF;。6.3 游标循环少处理最后一行EXIT WHEN cur_netnode%NOTFOUND如果放在FETCH之前第一行还没抓就判断直接退出。必须FETCH在前EXIT WHEN在后。6.4 DBMS_OUTPUT 没有输出先执行SET SERVEROUTPUT ON并且确认缓冲区大小够用SET SERVEROUTPUT ON SIZE 1000000。在 SQL Developer 里还要确认「DBMS Output」面板已经打开。6.5 FOR 循环上下限用了变量FOR i IN v_start..v_end LOOP会报PLS-00382。FOR 循环的边界只能是数字字面量。如果边界是动态的改用 WHILE 循环。6.6 插入时主键冲突seq_res_netnode_id.nextval如果序列当前值落后于表里已有数据会报ORA-00001。查一下序列当前值SELECT seq_res_netnode_id.nextval FROM dual;和表里最大 nodeid 对比必要时重建序列或调整增量。7. 把 AI 辅助接进你的存储过程开发流写存储过程时AI 最有用的三个场景解释报错、补全游标逻辑、生成测试数据。把前面配好的 TaoToken Key 用起来遇到ORA-开头的错误直接把错误码和你的 PL/SQL 块贴进模型对话页 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 让它结合上下文给修改建议。如果你要长期维护一套存储过程库建议走 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 把模型调用和代码仓库绑定改游标逻辑时让 AI 直接读文件。接入细节看文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Key 在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 管理。API 地址固定 https://taotoken.net/api 配置一次到处能用。最后给一个实用技巧把SYNC_NETNODE_DATA里的COMMIT改成每 1000 行提交一次用IF MOD(v_count, 1000) 0 THEN COMMIT; END IF;控制大批量数据时能避免 undo 表空间爆掉。这个改动我试过在百万级临时表上跑比一次性提交稳得多。
企业数字化 ERP 产品动态
相关推荐
从工具到技能:构建Agent技能系统的完整实战指南 1. 为什么Agent需要“技能”,而不只是“工具”这两年做大模型应用,我踩过最大的坑,就是所有人一上来就怼着Function Calling写代码,把一堆工具函数塞给模型,然后指望它“智能地”完成复杂任务。结果你也猜到了——模型… · 2026/9/25 10:09:28
华为Atlas 300V部署YOLO实战:从模型转换到推理优化 前段时间有个朋友问我:“Atlas 300V 24G这玩意儿到底是不是运算加速卡?我看有人拿它跑YOLO,有人说是视频卡,有点懵。”这个问题其实问到了点子上。华为Atlas这条产品线型号多、命名绕,很多人第一次接触都会卡在这个地方… · 2026/9/25 10:09:21
代码随想录/hello-algo学习笔记——二叉树 二叉树的基本概念
二叉树是一种非线性的数据结构,由每个节点一分为二引出两个子节点(类似高中生物学到的祖先后代的结构图,但二叉树是一个节点只能有两个子节点)。
基本单元:结点。每个节点包含值和两个引用࿰… · 2026/9/25 10:39:56
A2A供需匹配为什么不能只靠向量相似度 更新说明(2026年9月23日):本文是历史技术方案记录。当前 MapleBridge 用于采购询价、邀请买家已有的供应商联系人与报价比较,不提供供应商搜索、工厂核验或自动撮合。B2B 供需匹配为什么不能只靠向量相似度
最近在做一个 B2B 供需… · 2026/9/25 10:39:56
大模型网关密钥自动分配:MCP协议+CLI驱动的智能调度方案 1. 项目概述:为什么需要一个“自动分配密钥”的大模型网关调用中枢? 你有没有遇到过这样的场景:团队里五个人同时在调试同一个大模型应用,每人手里攥着一份从不同渠道申请来的API密钥——有人用的是Qwen的Key,有人配的… · 2026/9/25 10:39:50
JetBrains Mono 编程字体配置全指南:解决中文、连字与跨平台问题 1. 为什么 JetBrains Mono 是程序员真正需要的“呼吸感”字体JetBrains Mono 不是又一个标榜“等宽”的编程字体,它是 JetBrains 团队花了整整两年时间,盯着成千上万行真实代码、反复调整每一个字形轮廓、甚至为0和O的区分度单独设计视觉权重后ÿ… · 2026/9/25 10:39:50
IDURAR 开源 ERP/CRM 系统技术指南:基于 MERN 技术栈的功能架构、数据模型与部署实践 后端前端企业应用CRM 【免费下载链接】idurar-erp-crm Free Open Source ERP CRM Software Accounting Invoicing | Node.Js React 项目地址: https://gitcode.com/gh_mirrors/id/idurar-erp-crm 点击查看 免费下载 导读
本文以 IDURAR(idurar-erp-crm… · 2026/9/25 10:39:43
Highlight.io 开源可观测平台开发指南:从 Monorepo 结构到全栈构建部署的实战手册 可观测性后端 【免费下载链接】highlight highlight.io: The open source, full-stack monitoring platform. Error monitoring, session replay, logging, distributed tracing, and more. 项目地址: https://gitcode.com/gh_mirrors/hi/highlight 点击查看 免费下… · 2026/9/25 10:39:37
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37