接受字符串参数的函数和函数外可用的 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 中找到:

请查看该主题进行讨论,这可能会为您提供一些信息。