Oracle APEX中无需序列自动生成递增格式账单编号的PL/SQL实现
无需序列生成Oracle APEX账单编号(格式:INV1/23)
核心思路
通过查询现有账单表中的最大编号,提取数字部分递增后,拼接固定前缀INV和当前年份后两位(如23代表2023年),同时处理空表场景与并发冲突问题。
PL/SQL实现代码
基础生成逻辑(适用于表单自动赋值)
将以下代码用于APEX页面的计算项或提交前处理过程,假设页面项为P1_INVOICE_NO,账单表为invoices,编号字段为invoice_number:
DECLARE v_max_seq_num NUMBER; v_current_year CHAR(2); v_new_invoice_no VARCHAR2(20); BEGIN -- 获取当前年份后两位 v_current_year := TO_CHAR(SYSDATE, 'YY'); -- 提取现有最大编号的数字部分,空表时默认0 SELECT NVL(MAX(TO_NUMBER(SUBSTR(invoice_number, 4, INSTR(invoice_number, '/') - 4))), 0) INTO v_max_seq_num FROM invoices; -- 拼接生成新编号 v_new_invoice_no := 'INV' || TO_CHAR(v_max_seq_num + 1) || '/' || v_current_year; -- 赋值给APEX页面项 :P1_INVOICE_NO := v_new_invoice_no; END;
并发安全优化
如果存在多用户同时创建账单的场景,为避免重复编号,需添加行级锁:
DECLARE v_max_seq_num NUMBER; v_current_year CHAR(2); v_new_invoice_no VARCHAR2(20); BEGIN v_current_year := TO_CHAR(SYSDATE, 'YY'); -- 加锁避免并发冲突,跳过已锁定的记录 SELECT NVL(MAX(TO_NUMBER(SUBSTR(invoice_number, 4, INSTR(invoice_number, '/') - 4))), 0) INTO v_max_seq_num FROM invoices FOR UPDATE SKIP LOCKED; v_new_invoice_no := 'INV' || TO_CHAR(v_max_seq_num + 1) || '/' || v_current_year; :P1_INVOICE_NO := v_new_invoice_no; END;
APEX页面配置步骤
- 表单自动生成:在表单页面创建隐藏或只读页面项
P1_INVOICE_NO,设置其来源类型为PL/SQL代码,将上述基础逻辑代码填入来源值中,确保页面加载或提交前自动生成编号。 - 交互式报表展示:直接在报表中引用
invoice_number字段即可,无需额外配置。
注意事项
- 替换代码中的
invoices为你的实际账单表名,invoice_number为编号字段名。 - 年份会自动跟随系统时间切换(如2024年自动生成
INVx/24格式)。 - 若之前使用序列失败,大概率是未关联年份逻辑或拼接格式错误,此方案基于表数据动态生成,更适配年度递增的需求。
内容的提问来源于stack exchange,提问作者Hailtmalen
相关产品推荐
相关产品推荐

