Oracle SQL:根据字符串搜索返回字符串中的文本

时间:2013-11-27 15:34:39

标签: sql regex oracle plsql substring

以下是我要创建要查询的函数的文本示例:

"!PRINTSERVER.PAR
$MODE=QUIET
$DEBUG=N
$LOG_FILE=[file path]
$PRINTER_LIST=
-ACCOUNTS_LASER,\\print02\Accounts_Laser,winspool,Ne34:
-BE_PRINTER01,\\print01\BE_Printer01,winspool,Ne03:
-CUSTSERV_PRINTER,\\print01\CS_Laser,winspool,Ne06:

作为我的功能的'in'参数,我想搜索逻辑打印机名称,例如ACCOUNTS_LASER我想让它返回物理路径,例如\\print02\Accounts_Laser

此外,包含上述文本的相关字段的数据类型为long,因此我认为在将任何Oracle函数应用于字符串之前,它需要转换为字符串。

我猜我需要substrinstrregexp的组合,但是我们非常感谢您提供任何帮助。

4 个答案:

答案 0 :(得分:3)

正则表达式

'^(.*?' || 'ACCOUNTS_LASER' || ',)([^,]+)(.*)$'

标志

n

描述

^(.*?<Printer name goes here>',)([^,]+)(.*)$

Regular expression visualization

配方

-- INIT
create table test (input clob);

insert into test(input) values('
"!PRINTSERVER.PAR
$MODE=QUIET
$DEBUG=N
$LOG_FILE=[file path]
$PRINTER_LIST=
-ACCOUNTS_LASER,\\print02\Accounts_Laser,winspool,Ne34:
-BE_PRINTER01,\\print01\BE_Printer01,winspool,Ne03:
-CUSTSERV_PRINTER,\\print01\CS_Laser,winspool,Ne06:
');

-- SELECT
select
    regexp_replace(input, '^(.*?' || 'ACCOUNTS_LASER' || ',)([^,]+)(.*)$','\2', 1, 0, 'n') printer_path
from
    test

union all

select
    regexp_replace(input, '^(.*?' || 'BE_PRINTER01' || ',)([^,]+)(.*)$','\2', 1, 0, 'n') printer_path
from
    test

union all

select
    regexp_replace(input, '^(.*?' || 'CUSTSERV_PRINTER' || ',)([^,]+)(.*)$','\2', 1, 0, 'n') printer_path
from
    test

输出

|PRINTER_PATH              |
|--------------------------|
| \\print02\Accounts_Laser |
| \\print01\BE_Printer01   |
| \\print01\CS_Laser       |

答案 1 :(得分:1)

感谢所有发布建议的人。我在下面的答案中使用了一些sql来创建一个解决我问题的函数。

create or replace function get_printer_path (l_printer_name in varchar2)
return varchar2
is
  p_printer_path varchar2(5000);
  cursor temp is
  select 
    regexp_replace(dbms_xmlgen.getxmltype('select info from print_server where 
    server_name = ''STAGING'''), '.*-'|| l_printer_name ||',([^,]*),.*', '\1', 1, 1, 'n')
  from dual;
begin
  open temp;
  fetch temp into p_printer_path;

  if (p_printer_path not like '\\%') then
   p_printer_path := null;
  end if;

  close temp;
  return p_printer_path;
end get_printer_path;

任何进一步的改进或如果我违反任何标准做法,请继续发表评论。

答案 2 :(得分:0)

我显然不知道你的真实要求,但假设数据存储在名为test_tbl的表中,这样的事情可以让你走上正轨:

DECLARE
    FUNCTION printer_path(printer_name_in IN VARCHAR2)
    RETURN VARCHAR2
    IS
        v_retval VARCHAR2(1000);
    BEGIN
        FOR rec IN (select col from test_tbl)
        LOOP
            IF regexp_like(rec.col, '.*-'||printer_name_in||',([^,]*),.*', 'n')
            THEN
                v_retval := regexp_replace(rec.col, '.*-'||printer_name_in||',([^,]*),.*', '\1', 1, 1, 'n');
                EXIT; -- exit loop if data found (not sure what your real requirements are)
            END IF;
        END LOOP;
        RETURN v_retval;
    END printer_path;
BEGIN
    dbms_output.put_line('Path: '||printer_path('ACCOUNTS_LASER'));
END;

分解regexp_函数:

  • 匹配任何字符,后跟“ - ”,后跟传入的名称,后跟逗号,后跟任何不是逗号的内容,后跟逗号,后跟任何字符
  • ([^,] *)中的括号表示该信息可以在以后的反向引用中使用
  • 'n'作为匹配参数只允许“。”匹配新行字符。

我希望这会有所帮助,但请务必测试很多场景,因为我不知道您的数据实际上是什么样的!

答案 3 :(得分:0)

你正在处理两个完全独立的问题。首先是:

  

包含上述文本的相关字段的数据类型为长

LONG已被弃用,Oracle建议尽可能转换为CLOB,并提供大量文档和支持,以便从您的数据库中清除它们:http://docs.oracle.com/cd/E11882_01/appdev.112/e18294/adlob_long_lob.htm#ADLOB008

我认为这不是一种选择,因为这就是生活,而它永远不会。如果保证您的LONG列少于32k字符,则可以将其提取到最多32k的PL / SQL VARCHAR2字符串中,并使用正则表达式提取打印机路径

ETA:注意 - 如果你的长期是&gt;以下代码会出错。 32k ... L_ROW.STR实际上是一个隐藏的VARCHAR2(32676)

create table t_long (str long);

insert into t_long values (

'"!PRINTSERVER.PAR
$MODE=QUIET
$DEBUG=N
$LOG_FILE=[file path]
$PRINTER_LIST=
-ACCOUNTS_LASER,\\print02\Accounts_Laser,winspool,Ne34:
-BE_PRINTER01,\\print01\BE_Printer01,winspool,Ne03:
-CUSTSERV_PRINTER,\\print01\CS_Laser,winspool,Ne06:' 

 );

CREATE OR REPLACE FUNCTION GET_PRINTER_PATH (P_PRINTER_NAME IN VARCHAR2)
RETURN VARCHAR2
IS
    L_RESULT VARCHAR2(4000);
BEGIN
    FOR L_ROW IN  (SELECT STR FROM T_LONG) LOOP  
        L_RESULT:= REPLACE(REGEXP_SUBSTR(L_ROW.STR,'(^-'||P_PRINTER_NAME||',)([^,]*)',1,1,'m'),'-'||P_PRINTER_NAME||',');
        IF L_RESULT IS NOT NULL THEN 
            RETURN L_RESULT;
        END IF;
    END LOOP;
    RETURN NULL;
END;

WITH SAMPLE_NAMES AS( 
    SELECT 'ACCOUNTS_LASER' PRINTER_NAME FROM DUAL UNION ALL
    SELECT 'BE_PRINTER01' PRINTER_NAME FROM DUAL UNION ALL
    SELECT 'CUSTSERV_PRINTER' PRINTER_NAME FROM DUAL UNION ALL
    SELECT 'DUMMY1' PRINTER_NAME FROM DUAL)
SELECT PRINTER_NAME, GET_PRINTER_PATH (PRINTER_NAME) PRINTER_PATH FROM SAMPLE_NAMES;


PRINTER_NAME     PRINTER_PATH                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
ACCOUNTS_LASER   \\print02\Accounts_Laser                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
BE_PRINTER01     \\print01\BE_Printer01                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
CUSTSERV_PRINTER \\print01\CS_Laser                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
DUMMY1   

如果你的字符串超过32k,你可能想要分两个步骤:(1)创建一个使用CLOB的全局临时表(GTT)和(2)写一个类似的函数首先将数据放入GTT,然后对CLOB使用Regexp:

CREATE OR REPLACE FUNCTION GET_PRINTER_PATH_CLOB (P_PRINTER_NAME IN VARCHAR2)
RETURN VARCHAR2
IS
    PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    INSERT INTO T_CLOB
    SELECT TO_LOB(STR) FROM T_LONG;
    FOR L_ROW IN (SELECT REPLACE(REGEXP_SUBSTR(STR,'(^-'||P_PRINTER_NAME||',)([^,]*)',1,1,'m'),'-'||P_PRINTER_NAME||',') PRINTER_PATH
                  FROM   T_CLOB)
    LOOP
        IF L_ROW.PRINTER_PATH IS NOT NULL THEN
            COMMIT;
            RETURN L_ROW.PRINTER_PATH;
        END IF;
    END LOOP;
    COMMIT;                      
    RETURN NULL;        
END;