首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > oracle >

本人新手。求大神看看关于过滤分隔符提取字符串的有关问题,小弟我用数组实现异常好多

2013-08-06 
本人新手。。求大神看看关于过滤分隔符提取字符串的问题,我用数组实现错误好多题目是:编写存储过程,实现功能

本人新手。。求大神看看关于过滤分隔符提取字符串的问题,我用数组实现错误好多
题目是:
编写存储过程,实现功能:
1.输入参数:字符串,分隔符,序号
2.输出参数:字符串
3.注:序号可为负数,为负数时从右往左找字符串

例:
输入参数分别为: ab@@cd@@ee@@ff    @@   2    则输出:cd
输入参数分别为: ab@@cd@@ee@@ff    @@   -2   则输出:ee
输入参数分别为: ab@@cd@@ee@@ff    @@   4    则输出:ff

我写的代码如下 改了很多次


CREATE OR REPLACE PROCEDURE str_to(input     IN VARCHAR2,
                                   separator IN VARCHAR2,
                                   serialno  IN INTEGER) IS

  v_input       VARCHAR2(100) := input;
  v_separator   VARCHAR2(5) := separator;
  v_separatorno INTEGER;
  v_serialno    INTEGER := serialno;
  v_output      VARCHAR2(20);
  i             NUMBER;
  strlength     INTEGER;
  str           VARCHAR2(5);
  TYPE type_array IS VARRAY(200) OF VARCHAR2(20);
  array1 type_array;
  array2 type_array;
  flag   BOOLEAN;
  -- num    NUMBER;
  -- a      INTEGER;
BEGIN
  array1        := type_array();
  array2        := type_array();
  strlength     := length(v_input);
  v_separatorno := length(v_separator);
  flag          := FALSE;
  array2.extend;
  IF v_serialno < 0 THEN
    BEGIN
      v_serialno := -v_serialno;
      flag       := TRUE;
      SELECT REVERSE(v_input) INTO v_input FROM dual;
    END;


  END IF;
  --如果序号为负数,将输入的字符串反转
  FOR i IN 1 .. strlength LOOP
    array1.extend;
    array1(i) := substr(v_input, - (strlength - i + 1));
    --DBMS_OUTPUT.put_line(array1(i));
  END LOOP;
  COMMIT;
  --逆向剪切字符串,逐一存入数组
  -- a := -v_separatorno;
  FOR i IN 1 .. strlength LOOP
    --SELECT substr(array1(i), 1,v_separatorno) INTO str FROM dual;
    --DBMS_OUTPUT.put_line(str);
    IF substr(array1(i), 1, v_separatorno) <> v_separator THEN   --若数组元素不以分隔符为首将数组1的元素存到数组2中
      FOR j IN 1 .. array2.count LOOP
        --array1.extend;
        --array2.extend;
        array2(j) := array1(i);    --但是这里会出现以一个“@”为首的元素
       DBMS_OUTPUT.put_line(array2(j));
      END LOOP;
    END IF;
  END LOOP;
  array2.extend;
  /*v_output := array2(v_serialno);*/
  /*  SELECT INSTR(array2(v_serialno), '[^v_separator]+', 1, 1)
  INTO num
  FROM dual;*/  --扫描分隔符出现的位置
/*  SELECT SUBSTR(array2(v_serialno), 1, 2)
    INTO v_output
    FROM DUAL;*/
     SELECT SUBSTR(array2(v_serialno),
                         1,
                         v_serialno)
      INTO v_output
      FROM DUAL;  --从第一位开始截取,得到的结果是字符串的最后一位 有点搞不懂= =!
  IF flag = TRUE THEN
    BEGIN
      SELECT REVERSE(v_output) INTO v_output FROM dual;
    END;
  END IF; --当序号为负的时候保证输出的字符串是正向的
  DBMS_OUTPUT.put_line(v_output);
END str_to;

存储过程 分隔符
[解决办法]

引用:
Quote: 引用:

Quote: 引用:

对了 假如
BEGIN
  proc_str_to('ab@@cd@@ee@@ff@','@@',-2);
END;
输出的是ff 把@也当作分隔符了 这个好像不对


那你这个实际得到的结果是什么??


我改了一下 把length(replace(input, separator, '@')) 的@ 改成了# 输出了ee 这个是对的

但如果调用
BEGIN
  proc_str_to('ab@@cd@@ee@@ff@','@@',-1);
END;
输出的是ff 正确的应该是ff@


改了下,试下:

CREATE OR REPLACE PROCEDURE str_to(input     IN VARCHAR2,
                                   separator IN VARCHAR2,
                                   serialno  IN INTEGER,
                                   str       out varchar2) IS
  v_count   number;
  v_lv      number;
  v_input   varchar2(4000);
  v_replace varchar2(10) := '▽';
BEGIN

  v_input := replace(input, separator, v_replace);

  select length(v_input) - length(replace(v_input, v_replace, '')) + 1
    into v_count
    from dual;

  if (serialno >= 0) then
    v_lv := serialno;
  else
    v_lv := v_count + serialno + 1;
  end if;

  with t as
   (select level lv,


           regexp_substr(v_input, '[^' 
[解决办法]
 v_replace 
[解决办法]
 ']+', 1, level) str
      from dual
    connect by level <= v_count)
  select str into str from t where lv = v_lv;

  dbms_output.put_line(str);
exception
  when others then
    str := '';
END str_to;

热点排行