接受字符串参数的函数和函数外可用的 return 子字符串
Function to accept string parameter and return substrings usable outside of the function
我想编写一个接受输入字符串的函数,使用 REGEXP_SUBSTR 将该字符串解析为最多五个子字符串,然后 returns 将子字符串解析为调用该函数的过程。
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] || '%'
我怎样才能做到这一点?
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
用作列表不存在,所以你会得到一个子句 AND table_column LIKE '%%'
,它永远是真的,所以你可能需要更多的防御性编码来检查 PARSER_FUNCTION
中的 return 是否不是 NULL
.)
或者您可以删除该函数:
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 || '%' )
这意味着您的列表可以包含任意数量的元素,它会检查所有元素,而无需使用正则表达式重复调用提取列表项。
考虑这个函数:
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;
在此 post 中找到:
请查看该主题进行讨论,这可能会为您提供一些信息。
我想编写一个接受输入字符串的函数,使用 REGEXP_SUBSTR 将该字符串解析为最多五个子字符串,然后 returns 将子字符串解析为调用该函数的过程。
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] || '%'
我怎样才能做到这一点?
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
用作列表不存在,所以你会得到一个子句 AND table_column LIKE '%%'
,它永远是真的,所以你可能需要更多的防御性编码来检查 PARSER_FUNCTION
中的 return 是否不是 NULL
.)
或者您可以删除该函数:
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 || '%' )
这意味着您的列表可以包含任意数量的元素,它会检查所有元素,而无需使用正则表达式重复调用提取列表项。
考虑这个函数:
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;
在此 post 中找到:
请查看该主题进行讨论,这可能会为您提供一些信息。