【问题标题】:I am trying to write a function F_CHECK_STRING ,It checks if the complete word is found within the text我正在尝试编写一个函数 F_CHECK_STRING ,它检查是否在文本中找到完整的单词
【发布时间】:2021-07-28 01:21:28
【问题描述】:

编写一个函数 F_CHECK_STRING,它接受 2 个输入参数:

  • P_TEXT 类型的字符
  • P_WORD 类型的字符

它检查是否在文本中找到完整的单词返回 1 否则返回 0。搜索必须不区分大小写。

即:文本是由空格分隔的一组单词。

例子:

  • 文本是“In English Hello Word”,单词是“hello”,在本例中返回 1
  • 文本为“In English Hello word”,单词为“he”,本例返回0

 create or replace function F_CHECK_STRING (P_TEXT  in CHARACTER, 
                                            P_WORD  in CHARACTER,
                                            P_MESSAGE OUT VARCHAR2) 
 return NUMBER
 IS
 begin
  IF P_TEXT:= SUBSTR(LOWER('In English Hello Word'),12,5) LIKE LOWER ('hello');
  THEN
     RETURN 1;
  ELSE
     P_TEXT := SUBSTR(LOWER('In English Hello Word'),12,5) LIKE LOWER ('he');
  THEN
     RETURN 0;
  EXCEPTION
     WHEN OTHERS THEN
       P_MESSAGE := 'FAILED To Return ' || P_TEXT || '- SQL ERROR: '||SQLERRM;
end F_CHECK_STRING ;

【问题讨论】:

    标签: sql oracle oracle11g oracle10g stored-functions


    【解决方案1】:

    看完你的问题,你有多种可能,希望对你有帮助

    代码

    1. 使用 like 运算符
    create or replace function F_CHECK_STRING (P_TEXT  in VARCHAR2, 
                                                P_WORD  in VARCHAR2) 
    return NUMBER IS
    BEGIN
      IF (LOWER(P_TEXT) LIKE '% ' || LOWER(P_WORD) || ' %' ) THEN
        RETURN 1;
      ELSIF (LOWER(P_TEXT) LIKE LOWER(P_WORD) || ' %' ) THEN
        -- Matches the beginning of a string
        RETURN 1;
      ELSIF (LOWER(P_TEXT) LIKE '% ' || LOWER(P_WORD) || '' ) THEN
        -- Matches the end of a string
        RETURN 1;
      ELSE
        RETURN 0;
      END IF;
    END;
    /
    
    1. 使用substr运算符,请看上一个答案
    2. 使用 regexp_like 运算符(我的建议)
    create or replace function F_CHECK_STRING (P_TEXT  in VARCHAR2, 
                                                P_WORD  in VARCHAR2) 
    return NUMBER IS
    BEGIN
      -- \s means a whitespace character
      -- ^  Matches the beginning of a string.In multiline mode, it matches the beginning of any line anywhere within the source string.
      -- $  Matches the end of a string. In multiline mode, it matches the end of any line anywhere within the source string.
      -- 'i' specifies case-insensitive matching
      -- more https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Oracle-Regular-Expression-Support.html
      IF regexp_like (P_TEXT, '(^|\s)' || P_WORD || '(\s|$)', 'i') THEN
         RETURN 1;
      ELSE
         RETURN 0;
      END IF;
    END;
    /
    

    测试

    select F_CHECK_STRING ('In English Hello Word', 'hello') as "hello", 
           F_CHECK_STRING ('In English Hello Word', 'IN') as "IN",
           F_CHECK_STRING ('In English Hello Word', 'he') as "he",
           F_CHECK_STRING ('In English Hello Word', 'WORD') as "WORD"
    from dual;
    
    HELLO IN HE WORD 
    ----- -- -- ---- 
        1  1  0    1 
    
    

    提示

    可以在sql查询中使用regexp_like,无需创建自定义函数

    select 1 FROM DUAL
    where regexp_like ('In English Hello Word', '(^|\s)' || 'hello' || '(\s|$)', 'i') 
    ;
    
    select 1 FROM DUAL
    where regexp_like ('In English Hello Word', '(^|\s)' || 'he' || '(\s|$)', 'i') 
    ;
    
    SELECT CASE WHEN regexp_like ('In English Hello Word', '(^|\s)' || 'hello' || '(\s|$)', 'i')
           THEN 1
           ELSE 0
           END
    from dual;
    
    SELECT CASE WHEN regexp_like ('In English Hello Word', '(^|\s)' || 'he' || '(\s|$)', 'i')
           THEN 1
           ELSE 0
           END
    from dual;
    

    【讨论】:

      【解决方案2】:

      这样的事情可以吗?查看代码中的 cmets。

      SQL> create or replace function f_check_string
        2    (p_text in varchar2, p_word in varchar2)
        3  return number
        4  is
        5    l_len    number := length(p_word);
        6    l_pos    number;          -- position of P_WORD in P_TEXT
        7    l_char_a varchar2(1);     -- character in front of P_WORD
        8    l_char_b varchar2(1);     -- character behind P_WORD
        9    retval   number(1) := 0;  -- return value
       10  begin
       11    l_pos := instr(lower(p_text), lower(p_word));
       12
       13    if l_pos > 0 then
       14       -- word exists in text; see if it is complete
       15       l_char_a := case when l_pos = 1 then ' '
       16                        else substr(p_text, l_pos - 1, 1)
       17                   end;
       18       l_char_b := case when l_pos = 1 then ' '
       19                        else nvl(substr(p_text, l_pos + l_len, 1), ' ')
       20                   end;
       21
       22       -- everything is OK if both L_CHARs are empty strings
       23       if l_char_a = ' ' and
       24          l_char_b = ' '
       25       then
       26          retval := 1;
       27       end if;
       28    end if;
       29    return retval;
       30  end;
       31  /
      
      Function created.
      

      测试:

      SQL> select
        2    f_check_string('In English Hello Word', 'hello') res1,
        3    f_check_string('In English Hello Word', 'he'   ) res2,
        4    f_check_string('In English Hello Word', 'in'   ) res3,
        5    f_check_string('In English Hello Word', 'word' ) res4,
        6    f_check_string('In English Hello Word', 'ord'  ) res5
        7  from dual;
      
            RES1       RES2       RES3       RES4       RES5
      ---------- ---------- ---------- ---------- ----------
               1          0          1          1          0
      
      SQL>
      

      【讨论】:

        【解决方案3】:

        将字母数字字符视为单个单词,[[:alnum:]] POSIX 可用于将文本拆分为单词片段,如按 spacepunctuationspecial 分割字符所有这些都被认为在例外列表中这里的一个单词,如以下代码块:

        CREATE OR REPLACE FUNCTION F_Check_String ( i_text VARCHAR2, i_word VARCHAR2 ) 
        RETURN INT IS
           o_result  INT;
        BEGIN
           SELECT COUNT(*)
             INTO o_result
             FROM ( SELECT i_text FROM dual )
            WHERE LOWER(i_word) = REGEXP_SUBSTR(LOWER(i_text),'[[:alnum:]]+',1,level)
          CONNECT BY level <= REGEXP_COUNT(i_text,'[[:alnum:]]+');
        
           RETURN o_result;
        END;
        /
        

        Demo

        PS:在当前情况下,通过使用 COUNT 聚合,该函数不会抛出任何异常消息。因此,不需要 p_message OUT 参数

        【讨论】:

          【解决方案4】:

          为此使用REGEXP_LIKE。 '\W' 代表非单词字符。 '^' 是字符串的开头,'$' 是字符串的结尾。

          select 
            case when regexp_like (:p_text, '(^|\W)' || :p_word || '(\W|$)', 'i')
              then 1
              else 0
            end as match
          from dual;
          

          您当然可以将其包装在一个函数中:

          create or replace function f_check_string
          (
            p_text  in varchar2, 
            p_word  in varchar2
          ) return number is
          begin
            if regexp_like (p_text, '(^|\W)' || p_word || '(\W|$)', 'i') then 
              return 1;
            else 
              return 0;
            end if;
          end f_check_string;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-01-23
            • 1970-01-01
            • 2020-06-23
            • 2022-11-16
            • 2014-11-08
            • 2021-12-13
            • 2018-03-22
            相关资源
            最近更新 更多