函数接受字符串参数并返回在函数外部可用的子字符串

时间:2017-02-02 15:17:43

标签: oracle regexp-substr

我想编写一个接受输入字符串的函数,使用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] || '%'

我该如何做到这一点?

2 个答案:

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

请参阅该讨论的主题,以便为您提供一些信息。