ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Oracle 游标 cursor 实战:用 TaoToken 统一 Key 跑通成绩排名脚本

Oracle 游标 cursor 实战:用 TaoToken 统一 Key 跑通成绩排名脚本 1. 成绩排名脚本为什么总在游标这卡住Oracle 里做成绩排名很多人第一反应是开窗函数RANK()但真实项目里经常遇到更老的库、更复杂的并列规则或者需要在遍历过程中顺带写回名次字段这时候显式游标cursor就成了绕不开的写法。所谓显式游标你可以把它理解成给查询结果集装了一个可移动的指针FOR r IN cur_rank LOOP每转一圈就取一行配合WHERE CURRENT OF还能直接更新当前行特别适合边算边写的排名场景。这篇要解决的就是一条完整链路建成绩表、造测试数据、写一个用显式游标算总分并回填名次的存储过程最后通过 TaoToken 的统一 Key 和 API 通道把脚本调用动作串起来验证目标是一次跑通、看到正确的排名结果。适合正在学 PL/SQL 游标、或者手头有 Oracle 排名需求但不想只依赖窗口函数的朋友。下面所有 SQL 和配置都能直接复制我会把每一步的预期输出也写清楚方便你对照排查。2. 前置准备TaoToken 统一 Key 与调用通道在动手写游标之前先把调用通道这件事理清楚。TaoToken 在这里扮演的角色是统一入口你不需要为每个模型或每个脚本单独维护一套密钥而是拿一个 Key通过统一的 API 地址去发起请求。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个地址不加 UTM 参数。具体操作上你需要先去控制台创建一个 API Key然后把它写进本地配置文件。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建 Key 的页面在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到 Key 之后如果你用的是支持 TOML 配置的客户端或脚本框架可以按下面的片段写config.toml# config.toml [provider] name taotoken base_url https://taotoken.net/api api_key sk-你的TaoToken密钥 [model] default claude-3-5-sonnet timeout 60这里base_url一定要用不带 UTM 的 API 地址api_key换成你在控制台生成的那串。配置好之后你的排名脚本在需要调用模型做辅助比如生成测试数据、解释报错时就能走这条统一通道不用再到处找 Key。接入细节如果拿不准可以对照接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里的字段说明逐项核对。3. 可复制配置建表、造数与游标存储过程3.1 建表与造数 SQL先建成绩表tb_score字段包括学号、三科成绩和一个待回填的rank列。注意rank是 Oracle 的保留字之一建表时用它可以但查询时最好加引号或改名这里沿用原字段名rank实际项目建议改成rank_no更稳妥。create table tb_score ( id number(10) not null, sid varchar2(20) not null, chinese number(6,2), maths number(6,2), english number(6,2), rank number(10) ); insert into tb_score values(1,s0001,100,89,99,null); insert into tb_score values(2,s0002,66,58,24,null); insert into tb_score values(3,s0003,99,70,33,null); insert into tb_score values(4,s0004,46,78,88,null); insert into tb_score values(5,s0005,88,89,99,null); commit;造数完成后先select * from tb_score;看一眼五条记录、rank全为 null这就是我们的起点。3.2 显式游标存储过程骨架核心逻辑是声明一个带FOR UPDATE的游标循环遍历每一行算出总分再用一个子查询统计总分比我高的人数加 1 就是我的名次最后用WHERE CURRENT OF把名次写回当前行。create or replace procedure proc_upd_rank as -- 定义游标for update 允许后续按当前行更新 cursor cur_rank is select * from tb_score for update; -- 总分 totalScore number(10,2); -- 名次 v_rank number(10); begin for r in cur_rank loop -- 计算当前行总分 totalScore : r.maths r.chinese r.english; -- 统计总分高于当前行的人数1 得到名次 select count(*) into v_rank from tb_score where chinese maths english totalScore; v_rank : v_rank 1; -- 回填当前行名次 update tb_score set rank v_rank where current of cur_rank; end loop; commit; end; /这里有几个容易踩的点for update不能少否则where current of会报错totalScore和v_rank的声明要放在cursor之后、begin之前循环里用的是r.maths这种记录字段写法别写成cur_rank.maths。存储过程末尾的/是 SQL*Plus 里执行 PL/SQL 块的分隔符别漏。4. 验证请求调用脚本并核对排名结果存储过程编译通过后直接调用它SQL call proc_upd_rank(); Method called看到Method called说明过程执行成功。接着查询结果SQL select * from tb_score; ID SID CHINESE MATHS ENGLISH RANK --- ------ ------- ------ ------- ----- 1 s0001 100.00 89.00 99.00 1 2 s0002 66.00 58.00 24.00 5 3 s0003 99.00 70.00 33.00 4 4 s0004 46.00 78.00 88.00 3 5 s0005 88.00 89.00 99.00 2对照一下s0001 总分 288 排第 1s0005 总分 276 排第 2s0004 总分 212 排第 3s0003 总分 202 排第 4s0002 总分 148 排第 5。名次全部正确回填说明游标遍历和子查询计数这条链路是通的。如果你想让脚本调用也走 TaoToken 通道做辅助验证比如让模型帮你检查这段 PL/SQL 有没有语法隐患可以在配置好config.toml之后通过模型对话入口 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 把存储过程贴进去问一句这段游标逻辑有没有并发或空值风险。实测下来这种先本地跑通、再让模型复核的组合比纯靠肉眼查错效率高不少。5. 本篇常见错排查5.1 ORA-01002 或 where current of 报错最常见的原因是游标声明时漏了for update。where current of必须作用在带for update的游标上否则 Oracle 不知道你要更新哪一行。检查cursor cur_rank is select * from tb_score for update;这一行for update不能省。5.2 名次出现并列或跳号当前逻辑用的是count(*) 1属于标准竞赛排名总分相同的人会拿到相同名次后面的人跳号。比如两个人并列第 1下一个人是第 3。如果你要的是密集排名并列后不跳号把子查询改成统计总分严格大于当前行的去重总分个数即可select count(distinct chinese maths english) into v_rank from tb_score where chinese maths english totalScore; v_rank : v_rank 1;5.3 存储过程编译报错 PLS-00103多半是declare关键字用错了位置。在create or replace procedure ... as结构里as后面直接跟变量和游标声明不需要再写declare。原示例里如果照搬了匿名块的declare就会报PLS-00103: 出现符号 DECLARE。把declare删掉声明直接跟在as后面。5.4 调用后 rank 仍为 null先确认有没有commit。存储过程里我加了commit如果你手动去掉过更新只存在于当前会话换一个连接查就还是 null。另外确认调用的是proc_upd_rank()而不是只编译没执行。6. 把这条链路固定成你的日常工具跑通一次之后建议把建表、造数、存储过程、验证查询这四段整理成一个.sql脚本文件下次换数据直接改insert部分就行。如果你后续要做更复杂的排名比如按班级分组排名、多科目加权游标里可以再嵌套一层分组逻辑或者干脆在select里带上partition by的思路做对照。需要长期跑这类脚本、或者把排名逻辑接进自动化流程的话可以了解下 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 配合统一 Key 能把调用成本和管理动作收敛到一处。日常查 Key、看用量还是去控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 接入字段有疑问就翻文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。游标这东西写顺了之后你会发现它在边遍历边写回的场景里比窗口函数更直观。
返回列表