短名称功能无法正常工作

时间:2013-07-26 07:33:41

标签: oracle plsql

来自表MMSTREPHDR的generatig唯一短名称的代码。 我在MMSTREPHDR中已有短名kvkv1kv2kv3。但是在传递参数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;

3 个答案:

答案 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;