我想编写一个接受输入字符串的函数,使用REGEXP_SUBSTR将该字符串解析为最多五个子字符串,并将子字符串返回给调用该函数的过程。
CREATE OR REPLACE FUNCTION PARSER_FUNCTION
(inputString IN VARCHAR2)
RETURN VARCHAR2
AS
subStrings VARCHAR2(100);
CURSOR C1 IS
SELECT REGEXP_SUBSTR(inputString, '[[:alpha:]]+', 1, 1)
, REGEXP_SUBSTR(inputString, '[[:alpha:]]+', 1, 2)
, REGEXP_SUBSTR(inputString, '[[:alpha:]]+', 1, 3)
, REGEXP_SUBSTR(inputString, '[[:alpha:]]+', 1, 4)
, REGEXP_SUBSTR(inputString, '[[:alpha:]]+', 1, 5)
FROM DUAL;
BEGIN
OPEN C1;
/* Not sure what to do here... */
RETURN subStrings;
END;
END PARSER_FUNCTION;
在调用此函数的存储过程的WHERE子句中,我希望能够将列与五个子字符串中的每一个进行比较,如:
WHERE table_column LIKE '%' || PARSER_FUNCTION[1] || '%'
AND table_column LIKE '%' || PARSER_FUNCTION[2] || '%'
AND table_column LIKE '%' || PARSER_FUNCTION[3] || '%'
AND table_column LIKE '%' || PARSER_FUNCTION[4] || '%'
AND table_column LIKE '%' || PARSER_FUNCTION[5] || '%'
我该如何做到这一点?
答案 0 :(得分:1)
CREATE OR REPLACE FUNCTION PARSER_FUNCTION(
inputString IN VARCHAR2,
index IN NUMBER
)
RETURN VARCHAR2 DETERMINISTIC
AS
RETURN REGEXP_SUBSTR( inputString, '[[:alpha:]]+', 1, index );
END PARSER_FUNCTION;
/
或者,没有正则表达式:
CREATE OR REPLACE FUNCTION parser_function(
list IN VARCHAR2,
position IN NUMBER,
delimiter IN VARCHAR2 DEFAULT ','
)
RETURN VARCHAR2 DETERMINISTIC
IS
p_start NUMBER := 1;
p_end NUMBER;
BEGIN
IF list IS NULL OR position < 1 THEN
RETURN NULL;
END IF;
IF position > 1 THEN
p_start := INSTR( list, delimiter, 1, position - 1 ) + 1;
IF p_start = 1 THEN
RETURN NULL;
END IF;
END IF;
p_end := INSTR( list, delimiter, 1, position );
IF p_end = 0 THEN
p_end := LENGTH( list ) + 1;
END IF;
RETURN SUBSTR( list, p_start, p_end - p_start );
END;
/
然后你可以这样做:
WHERE table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 1 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 2 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 3 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 4 ) || '%'
AND table_column LIKE '%' || PARSER_FUNCTION( 'list,list2,list3', 5 ) || '%'
(注意:这适用于在where子句中使用AND
但在使用OR
作为列表中的第4和第5个条目时可能不适用的情况; t存在所以你会得到一个AND table_column LIKE '%%'
的句子,它总是正确的,所以你可能需要更多的防御性编码来检查PARSER_FUNCTION
的回报是否不是NULL
。)< / em>的
或者你可以摆脱这个功能:
WHERE table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 1 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 2 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 3 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 4 ) || '%'
AND table_column LIKE '%' || REGEXP_SUBSTR( 'list,list2,list3', '[[:alpha:]]+', 1, 5 ) || '%'
<强>更新强>:
您还可以将列表转换为集合并将其连接到您的查询:
CREATE OR REPLACE FUNCTION split_String(
i_str IN VARCHAR2,
i_delim IN VARCHAR2 DEFAULT ','
) RETURN SYS.ODCIVARCHAR2LIST DETERMINISTIC
AS
p_result SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
p_start NUMBER(5) := 1;
p_end NUMBER(5);
c_len CONSTANT NUMBER(5) := LENGTH( i_str );
c_ld CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
IF c_len > 0 THEN
p_end := INSTR( i_str, i_delim, p_start );
WHILE p_end > 0 LOOP
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
p_start := p_end + c_ld;
p_end := INSTR( i_str, i_delim, p_start );
END LOOP;
IF p_start <= c_len + 1 THEN
p_result.EXTEND;
p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
END IF;
END IF;
RETURN p_result;
END;
/
然后你可以这样做:
SELECT *
FROM your_table t
WHERE NOT EXISTS( SELECT 1
FROM TABLE( split_String( 'list1,list2,list3' ) l
WHERE t.table_column NOT LIKE '%' || l.COLUMN_VALUE || '%' )
这意味着您的列表可以包含任意数量的元素,并且它将全部检查它们,而无需使用正则表达式重复调用提取列表项。
答案 1 :(得分:0)
考虑这个功能:
FUNCTION GET_LIST_ELEMENT(string_in VARCHAR2, element_in NUMBER, delimiter_in VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS
BEGIN
RETURN REGEXP_SUBSTR(string_in, '(.*?)(\'||delimiter_in||'|$)', 1, element_in, NULL, 1);
END GET_LIST_ELEMENT;
如本帖所示:
https://stackoverflow.com/a/25652018/2543416
请参阅该讨论的主题,以便为您提供一些信息。