来自表MMSTREPHDR的generatig唯一短名称的代码。
我在MMSTREPHDR中已有短名kv
,kv1
,kv2
,kv3
。但是在传递参数kv时它给了我kv1
而不是kv4
(因为它在LOOP中)。无法弄清楚出了什么问题?
FUNCTION FUN_GENERATE_SNAME (p_name VARCHAR2)
RETURN VARCHAR2
IS
vl_sname VARCHAR2 (15);
n_cnt NUMBER := 1;
vl_sub NUMBER;
CURSOR c1 (vl_sname VARCHAR2)
IS
SELECT a.repsname, a.repcode
FROM MMSTREPHDR a
WHERE TRIM (UPPER (a.repsname)) = TRIM (UPPER (vl_sname));
BEGIN
vl_sname := TRIM (SUBSTR (p_name, 1, 15));
FOR i IN c1 (vl_sname)
LOOP
vl_sub := LENGTH (TO_CHAR (n_cnt));
vl_sname := SUBSTR (vl_sname, 1, (15 - vl_sub)) || n_cnt;
n_cnt := n_cnt + 1;
END LOOP;
RETURN vl_sname;
EXCEPTION
WHEN OTHERS
THEN
RETURN vl_sname;
END fun_generate_sname;
答案 0 :(得分:1)
您的起始参数是'kv'。这是您传递给光标的内容。因此,您的光标将选择一行,即MMSTREPHD.repsname = 'kv'
行。
所以你的循环逻辑将被执行一次。所以cnt
= . Hence
vl_sname`变为'kv1',这是循环退出时得到的值。
解决这个问题的最简单方法是承认MMSTREPHD.repsname
是一个智能密钥,由两个元素组成:子系统名称和报告编号。将列拆分为两列将使得查找给定子系统的下一个报告编号变得简单。您甚至可以将复合值保留为虚拟列(11g或更高版本),或者使用稍微有点的触发器来维护它。
否则:
select concat(p_name
, trim(to_char(max(to_number(nvl(replace(repsname,p_name),'0')))+1)) )
into vl_sname
from MMSTREPHD
where repsname like p_name||'%'
警告 - 我还没有对此进行测试,因此括号可能无法正确配对。
答案 1 :(得分:0)
您将以下语句连接为
vl_sname := SUBSTR (vl_sname, 1, (15 - vl_sub)) || n_cnt;
这里n_cnt在上面的代码中给它的初始值为1,这就是为什么它取值为KV1的原因。你应该将它保持为null并且语句之后应该在循环中将它递增1。希望将是有用的
答案 2 :(得分:0)
尝试此功能
function FUN_GENERATE_SNAME(p_name varchar2) return varchar2 is
l_idx number;
l_name_ln := length(trim(p_name));
begin
select max(substr(trim(UPPER(a.repsname)), 1, -length(trim(UPPER(a.repsname)) + l_name_ln))
into l_idx
from MMSTREPHDR a
where substr(trim(UPPER(a.repsname)), 1, l_name_ln) = trim(UPPER(vl_sname));
if l_idx is null then
-- mean name is unique
return vl_sname;
else
return vl_sname ||(l_idx + 1);
end if;
exception
when others then
return vl_sname;
end fun_generate_sname;