Oracle中无需包实现带序号的Push过程与Pop函数求助
实现无包的Push存储过程和Pop函数(栈功能)
原包代码的错误分析
你提供的包代码存在以下问题导致报错:
pop函数内重复定义子类型时语法错误:subtype my_string_subtype varchar2(100);缺少关键字is,且该定义完全多余(包体已定义过相同子类型)pop函数中使用的val变量未声明,需要在函数声明段添加变量定义
如果只是修正包代码,修正后的版本如下(但你明确要求不用包,所以仅作参考):
create or replace package pushpop_demo as procedure push(val varchar2); function pop return varchar2; end pushpop_demo; / create or replace package body pushpop_demo as subtype my_string_subtype is varchar2(100); type varchar2_ntt is table of my_string_subtype; stuff varchar2_ntt := varchar2_ntt(); procedure push(val varchar2) is begin stuff.extend; stuff(stuff.last) := val; end push; function pop return varchar2 is val my_string_subtype; -- 声明变量 begin if stuff is not empty then val := stuff(stuff.last); stuff.delete(stuff.last); end if; return val; end pop ; end pushpop_demo; /
无包的实现方案(使用临时表+序列)
由于不使用包的话无法维持会话级的内存集合,我们可以用会话级临时表来存储栈数据,配合序列维护栈的顺序:
1. 创建会话临时表
临时表的作用是存储每个会话独立的栈数据,提交后保留数据(保证会话内栈状态持续):
CREATE GLOBAL TEMPORARY TABLE stack_table ( stack_seq NUMBER PRIMARY KEY, stack_val VARCHAR2(100) ) ON COMMIT PRESERVE ROWS;
2. 创建序列生成栈元素序号
用序列保证每个栈元素的序号唯一,序号最大的元素即为栈顶:
CREATE SEQUENCE stack_seq START WITH 1 INCREMENT BY 1;
3. 实现Push存储过程
向临时表插入元素,使用序列生成序号:
CREATE OR REPLACE PROCEDURE push(p_val VARCHAR2) IS BEGIN INSERT INTO stack_table (stack_seq, stack_val) VALUES (stack_seq.NEXTVAL, p_val); END push; /
4. 实现Pop函数
查询并删除栈顶(最大序号)的元素,返回对应的值:
CREATE OR REPLACE FUNCTION pop RETURN VARCHAR2 IS v_val VARCHAR2(100); v_max_seq NUMBER; BEGIN -- 获取当前栈的最大序号(栈顶位置) SELECT MAX(stack_seq) INTO v_max_seq FROM stack_table; IF v_max_seq IS NOT NULL THEN -- 获取栈顶值 SELECT stack_val INTO v_val FROM stack_table WHERE stack_seq = v_max_seq; -- 删除栈顶元素 DELETE FROM stack_table WHERE stack_seq = v_max_seq; END IF; RETURN v_val; END pop; /
方案说明
- 临时表
stack_table是会话隔离的,每个会话操作的都是自己的栈数据,不会互相干扰 - 序列
stack_seq保证了元素入栈的顺序,Pop时通过最大序号定位栈顶,符合栈"后进先出"的特性 - 如果需要清空栈,直接执行
DELETE FROM stack_table;即可
内容的提问来源于stack exchange,提问作者Big Dream American
相关产品推荐
相关产品推荐

