-- 动态生成字母方式主键,A-Z 大于Z自动进位【26进制数值表示】
-- 参数:动态查询表和主键列
create or replace function charkey (tabName char, pkName char) return char
as
v_key varchar2(4); -- 表中查询出当前主键列最大值
v_char varchar2(4) := ''; -- 输出用变量
v_len number(1); -- 查询出最大值字符串长度
v_i number(1); -- 循环控制变量
v_c char(1); -- 提取单个字符变量
v_flag number(1) := 1; -- 是否'进位'变量
v_count number; -- 查询表中记录总数
begin
-- 查询表中记录数
execute immediate 'select count(1) from ' || tabName into v_count;
-- 如果表中没有记录,则返回'A'
if (v_count = 0) then
v_char := 'A';
return v_char;
end if;
-- 获取指定表中主键列当前最大值
execute immediate 'select ' || pkName || ' from ' ||
'(select rownum r, t.' || pkName || ' from ' ||
'(select ' || pkName || ' from ' || tabName ||
' order by length(' || pkName || ') desc, ' || pkName || ' desc) t) where r < 2'
into v_key;
-- 字符串长度
v_len := length(v_key);
-- 循环控制变量
v_i := v_len;
-- 从最后一个字符开始,向前循环遍历
while v_i >= 1 loop
v_c := substr(v_key, v_i, 1);
-- 如果需要进位,当前字符+1
if(v_flag = 1) then
v_c := chr(ascii(v_c)+1);
v_flag := 0;
end if;
-- 当前字符超出上限
if( ascii(v_c) > ascii('Z')) then
v_c := 'A';
v_flag := 1;
end if;
v_char := v_c || v_char;
v_i := v_i - 1;
end loop;
-- 如果遇到ZZ情况,需要补充一位'A'
if(v_flag = 1) then
v_char := 'A' || v_char;
end if;
return v_char;
end;
-- 测试表
create table testtab
(
id varchar2(4) primary key,
val number(4)
);
-- 测试通过函数动态生成主键插入数据
declare
v_count number(9) := 1;
begin
while v_count <= 30 loop
insert into testtab values(charkey('testtab','id'), 1);
v_count := v_count + 1;
end loop;
end;
select * from testtab;