【问题标题】:Oracle SQL: Return text in string based on search of stringOracle SQL:根据字符串搜索返回字符串中的文本
【发布时间】:2013-12-13 08:07:48
【问题描述】:

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

"!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 的组合,但我们将不胜感激。

【问题讨论】:

    标签: sql regex oracle plsql substring


    【解决方案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】:

      正则表达式

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

      标志

      n
      

      说明

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

      食谱

      -- 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       |
      

      【讨论】:

      • 只是好奇:您是如何创建说明正则表达式的图像的?
      【解决方案3】:

      您正在处理两个完全独立的问题。第一个是这样的:

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

      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:注意 - 如果您的 long 大于 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;
      

      【讨论】:

        【解决方案4】:

        我显然不知道您的真正要求,但假设数据存储在名为 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' 作为匹配参数只允许“.”匹配换行符。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-08-05
          • 2018-12-06
          • 2014-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-20
          相关资源
          最近更新 更多