oracle substring返回错误的文本

时间:2016-01-20 00:29:52

标签: oracle parsing substr

运行时下面的函数返回错误的文本。例。表A包含msg_id和msg_text。表B包含要解析的字符串。

由于某种原因,我能够正确地从表B中的字符串中提取所有msg_id的位置。如在起始位置2结束位置4.但是当它实际从表B中提取字符串substr(result_val,strt, endstr)返回太多文本或不够。它可能会为子字符串添加一个空格,或者它可能会在末尾添加更多文本。但实际坐标正确匹配我需要提取的文本。看起来像substr取出了不同的价值。任何想法?

特别是变量"提取"显示我正在寻找的正确ID,但只要我尝试在任何地方找到该ID,我就会得到错误的结果。

以下是我在双重

中的内容
select ('@1 @2') from dual
Output:My comment for number 1 My comment for number 2

select (' @1 @2') from dual
Output: nothing

select ('@1') from dual
output: My comment for number 1

select result_parm(' @1') from dual;
output:  My comment for number 1 --note it did add the space correctly

select result_parm(' @1 @2') from dual;
output: none

幕后DBMS输出在解析时向我显示以下内容 ' @ 1 @ 2 @ 3'。我不得不注释掉替换部分,似乎有些东西在那里打破并且在第二个项目之后阻止任何解析。

幕后的dbms输出: 开始字符串1 结束字符串2 @ 1< - 用substr抓住了@ 1,但是在1之后它还抓住了一个额外的空间 开始字符串4 结束字符串5 @ 2 @ 3< - 为什么在位置清楚地说4,5时它错误地抓住@ 2和@ 3        我有一种感觉,这也是杀死替换但不确定原因的原因 开始字符串7 结束字符串8 @ 3< - 正确抓取

表:

create table REC_CANNED_COMM
(
  ENTRY_NUM   INTEGER not null,
  MSG_ID      VARCHAR2(5),
  MSG_TEXT    VARCHAR2(200)
);

create table REC_RESULT
(
ENTRY_NUM  INTEGER not null,
RESULT_TXT VARCHAR2(200)
);


insert into rec_result values ('1','@1');
insert into rec_result values ('2','@1 and @2');
insert into rec_result values ('3','@1 and @2 and @3');
insert into rec_result values ('4','this is entry @4');
insert into rec_result values ('5','This one has no canned message');

insert into rec_canned_comm values ('1','@1','My comment for number 1');
insert into rec_canned_comm values ('2','@2','My comment for number 2');
insert into rec_canned_comm values ('3','@3','My comment for number 3');
insert into rec_canned_comm values ('4','@4','My comment for number 4');
insert into rec_canned_comm values ('5','@5','My comment for number 5');

CREATE OR REPLACE FUNCTION result_parm(result_val VARCHAR2) 
RETURN VARCHAR2   IS      
  num         NUMBER;
  tmp         VARCHAR2(2000);
  strt        NUMBER;
  endstr      NUMBER;
  tmp_msg     VARCHAR2(2000);
  tmp_msg_txt VARCHAR2(2000);
  extracted   VARCHAR2(2000);

  BEGIN

    tmp := result_val;
    num := regexp_count(result_val, '@');
    IF (num = 0)
    THEN RETURN result_val;
    END IF;

    FOR loop_count IN 1..num
    LOOP

      tmp_msg := '';
      tmp_msg_txt := '';

      strt := instr(result_val, '@', 1, loop_count);
      endstr := CASE
                WHEN regexp_instr(result_val,
                                  '[\,\.\;\:\''\     <\>\/\+\-]|\s',
                                  instr(result_val, '@', 1, loop_count)) = 0
                  THEN length(result_val)
                WHEN regexp_instr(result_val,
                                  '^[\,\.\;\:\''\<\>\/\+\-]|\s',
                                  instr(result_val, '@', 1, loop_count)) > 0
                  THEN regexp_instr(result_val,
                                    '^[\,\.\;\:\''\<\>\/\+\-]|\s',
                                    instr(result_val, '@', 1, loop_count)) - 1
                END;

      dbms_output.put_line('start string ' || strt);
      dbms_output.put_line('end string ' || endstr);

      extracted := substr(result_val, strt, endstr);

      dbms_output.put_line(extracted);

      SELECT
        rec_canned_comm.msg_id,
        rec_canned_comm.msg_text
      INTO tmp_msg,
           tmp_msg_txt
      FROM rec_canned_comm
      WHERE rec_canned_comm.msg_id = extracted;

      tmp := replace(tmp, tmp_msg, tmp_msg_txt);
    END LOOP;

    RETURN tmp;

  END;

1 个答案:

答案 0 :(得分:0)

我不恰当地使用了endtr。你在哪里看到instr或substr中的endstr应该是(endstr - strt +1)。我使用的是位置位置而不是字符长度。这一切都有所不同。