使用CURSOR编写PL/SQL程序实现表内单词频数分布统计
前置准备
首先确认表结构符合要求:默认初始表
intitaltableA存储单词的列名为WORD,如果你的实际列名不同请自行替换。如果还未创建结果表finaltableA,先执行建表语句:
CREATE TABLE finaltableA (WORDS VARCHAR2(100), WCOUNTS NUMBER);
执行统计前建议先清空结果表历史数据,避免重复统计:
TRUNCATE TABLE finaltableA;
实现方案1(完全匹配插入+更新要求,适合初学者理解)
逐行遍历初始表的所有单词记录,判断单词是否已存在于结果表,存在则更新计数,不存在则插入新记录,完全符合要求的游标+插入更新操作逻辑:
DECLARE -- 声明游标:遍历初始表所有单词记录 CURSOR c_word_list IS SELECT WORD FROM intitaltableA; -- 存储游标取出的单个单词 v_word intitaltableA.WORD%TYPE; -- 存储单词在结果表中的已有计数 v_count NUMBER; BEGIN OPEN c_word_list; LOOP -- 从游标取单条数据 FETCH c_word_list INTO v_word; -- 游标数据取完后退出循环 EXIT WHEN c_word_list%NOTFOUND; -- 查询当前单词是否已在结果表存在 SELECT COUNT(*) INTO v_count FROM finaltableA WHERE WORDS = v_word; -- 存在则计数+1,不存在则插入新记录 IF v_count > 0 THEN UPDATE finaltableA SET WCOUNTS = WCOUNTS + 1 WHERE WORDS = v_word; ELSE INSERT INTO finaltableA (WORDS, WCOUNTS) VALUES (v_word, 1); END IF; END LOOP; CLOSE c_word_list; COMMIT; DBMS_OUTPUT.PUT_LINE('单词频数统计完成'); EXCEPTION -- 异常处理:出错回滚并关闭游标 WHEN OTHERS THEN ROLLBACK; DBMS_OUTPUT.PUT_LINE('统计出错,错误信息:' || SQLERRM); IF c_word_list%ISOPEN THEN CLOSE c_word_list; END IF; END; /
实现方案2(优化版,适合数据量较大的场景)
游标直接预先统计好每个单词的总出现次数,再批量写入结果表,循环次数更少、执行效率更高:
DECLARE -- 游标先聚合统计每个单词的总出现次数 CURSOR c_word_counts IS SELECT WORD, COUNT(*) AS total FROM intitaltableA GROUP BY WORD; v_word intitaltableA.WORD%TYPE; v_total NUMBER; BEGIN OPEN c_word_counts; LOOP FETCH c_word_counts INTO v_word, v_total; EXIT WHEN c_word_counts%NOTFOUND; -- 直接插入预统计好的结果 INSERT INTO finaltableA (WORDS, WCOUNTS) VALUES (v_word, v_total); END LOOP; CLOSE c_word_counts; COMMIT; DBMS_OUTPUT.PUT_LINE('单词频数统计完成'); EXCEPTION WHEN OTHERS THEN ROLLBACK; DBMS_OUTPUT.PUT_LINE('统计出错,错误信息:' || SQLERRM); IF c_word_counts%ISOPEN THEN CLOSE c_word_counts; END IF; END; /
注意事项
- 如果单词长度超过100,需要调整
finaltableA的WORDS字段长度 - 执行前确认你有两张表的读写、事务提交权限
内容的提问来源于stack exchange,提问作者Rashmi Agnihotri
相关产品推荐
相关产品推荐

