以下是我要创建要查询的函数的文本示例:
"!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函数应用于字符串之前,它需要转换为字符串。
我猜我需要substr
和instr
或regexp
的组合,但是我们非常感谢您提供任何帮助。
答案 0 :(得分:3)
'^(.*?' || '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 |
答案 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_函数:
我希望这会有所帮助,但请务必测试很多场景,因为我不知道您的数据实际上是什么样的!
答案 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;