oracle substring returns 错误文本

oracle substring returns wrong text

运行returns错误文本时的功能如下。例子。 Table A 包含 msg_id 和 msg_text。 Table B 包含要解析的字符串。

出于某种原因,我能够从 Table B 中的字符串中正确提取所有 msg_id 的位置。如开始位置 2 结束位置 4。但是当涉及到实际提取时from table B string substr (result_val, strt,endstr) returns 文本太多或不够。它可能会向子字符串添加 space,或者可能会在末尾添加更多文本。但实际坐标与我需要提取的文本正确匹配。似乎 substr 取了一个不同的值..有什么想法吗?

具体来说,变量 "extracted" 显示了我正在寻找的正确 ID,但是当我尝试在任何地方找到该 ID 时,我得到了错误的结果。

这是我在 dual

中放置的内容
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 之后抓取了一个额外的 space 开始字符串 4 结束字符串 5 @2 @3 <-- 为什么它抓错了@2 和@3 而位置明明是 4,5 我有一种感觉,这也是杀死替换的原因,但不确定为什么 开始字符串 7 结束字符串 8 @3 <--抓取正确

Tables:

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;

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