代码改变世界

主键字母自动生成函数(随摘)

2014-02-12 17:35  defended  阅读(616)  评论(0编辑  收藏  举报

-- 动态生成字母方式主键,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;