regexp_like正则表达式写法求助

blank7 2014-03-28 11:52:16
使用regexp_like函数判断传入字符串是否符合格式如:1111,22221,.....,33332
1. 逗号为各子串分割符
2. 各子串仅为数字组成,最长不超过20位
3. 字符串不能包含数字及逗号以外的字符
4. 无限定字符串包含多少个子串
...全文
673 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
blank7 2014-04-01
  • 打赏
  • 举报
回复
引用 6 楼 hdg5211314 的回复:
亲,都是我一个人在回复,我把sql丢给你吧,写了我半个小时
--函数只是用于判断是否纯数字以及带符号的
CREATE OR REPLACE FUNCTION ONERE_TO_MANYRE(VALUE1 IN VARCHAR2,--这个是字符串
                                           SYMBOL IN CHAR) RETURN VARCHAR2 IS--这个是你的判断字符,在你的需求里面是分号
    RESULT      VARCHAR2(100);
    STRING_NUM1 NUMBER;
    STRING_NUM2 NUMBER;
    Number_flag CHAR(1);
    reg_exp     NVARCHAR2(100);
BEGIN
    reg_exp := '^[1-9][0-9]*(' || SYMBOL || '[0-9]*)*';
    SELECT COUNT(CASE LENGTH(REGEXP_SUBSTR(a, reg_exp))
                     WHEN LENGTH(A) THEN
                      a
                 END) B
      INTO Number_flag
      FROM (SELECT VALUE1 a FROM dual);
    IF Number_flag = 0 THEN
        RESULT := '存在非数字';
    ELSIF Number_flag = 1 THEN
    
        --这是使用正则表达式判断进行拆分(注:这个有缺陷)
        SELECT COUNT(*)
          INTO STRING_NUM2
          FROM (sELECT DISTINCT regexp_substr(a, '[[:digit:]]+', 1, level) t
                  from (SELECT VALUE1 a FROM DUAL)
                connect by level <=
                           length(regexp_replace(a, '[[:digit:]]+')))
         WHERE length(t) >= 20;
    
        IF STRING_NUM2 >= 1 THEN
            RESULT := '存在超过20个字符的子字符';
        ELSE
            RESULT := '有效字符';
        END IF;
    END IF;
    /* --未使用正则表达式对源字符进行拆分并判断,不建议使用这个
    SELECT COUNT(*)
      INTO STRING_NUM1
      FROM (SELECT SUBSTR(SYMBOL || A.STR || SYMBOL,
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) + 1,
                          INSTR(SYMBOL || A.STR || SYMBOL,
                                SYMBOL,
                                1,
                                ROWNUM + 1) -
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) - 1) T
              FROM (SELECT VALUE1 STR FROM DUAL) A, ALL_OBJECTS
             WHERE ROWNUM <
                   LENGTH(SYMBOL || A.STR || SYMBOL) -
                   LENGTH(REPLACE(SYMBOL || A.STR || SYMBOL, SYMBOL)))
     WHERE LENGTH(T) >= 20;
    
    IF STRING_NUM1 >= 1 THEN
        RESULT := '存在超过20个字符的子字符';
    END IF;*/
    RETURN(RESULT);
END ONERE_TO_MANYRE;
我后来降低要求了,直接判断数字还有逗号分隔,子串长度就不判断了
流浪川 2014-03-31
  • 打赏
  • 举报
回复
引用 4 楼 blank7 的回复:
[quote=引用 1 楼 hdg5211314 的回复:] 为了你这个问题,我还真是想了很久,首先分享一个观点吧: oracle对正则支持很浅,建议不使用在oracle中使用正则表达式,因为容易造成low performance。由于你的条件比较多,我的sql也比较复杂,肯定我的有值得优化的地方,嘿嘿,新手路过。
 WITH TS AS
 (SELECT '1111,222,3312' A FROM DUAL UNION ALL
 SELECT '1,2,3,4,5,6' FROM  DUAL UNION ALL
 SELECT '66,77' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  )

 SELECT DISTINCT a,regexp_substr(a,'[[:alnum:]]+',1,level) t,LEVEL e
 from ts
    connect by level<=length(regexp_replace(a,'[[:alnum:]]+'))+1
我最初的想法是直接用regexp_like来判断格式,不知道可不可行,如果一句正则表达式就能把格式覆盖的话效率就不会低,如果不行的话我是打算直接用自定义函数做[/quote] 直接用实现不了,因为你每一段还有判断规则。。先按1楼的方法分割以后,再判断分割的时候存在不满足或者超过20的。。取count值即可,如果count为0即满足否者不满足。
blank7 2014-03-31
  • 打赏
  • 举报
回复
引用 1 楼 hdg5211314 的回复:
为了你这个问题,我还真是想了很久,首先分享一个观点吧: oracle对正则支持很浅,建议不使用在oracle中使用正则表达式,因为容易造成low performance。由于你的条件比较多,我的sql也比较复杂,肯定我的有值得优化的地方,嘿嘿,新手路过。
 WITH TS AS
 (SELECT '1111,222,3312' A FROM DUAL UNION ALL
 SELECT '1,2,3,4,5,6' FROM  DUAL UNION ALL
 SELECT '66,77' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  )

 SELECT DISTINCT a,regexp_substr(a,'[[:alnum:]]+',1,level) t,LEVEL e
 from ts
    connect by level<=length(regexp_replace(a,'[[:alnum:]]+'))+1
我最初的想法是直接用regexp_like来判断格式,不知道可不可行,如果一句正则表达式就能把格式覆盖的话效率就不会低,如果不行的话我是打算直接用自定义函数做
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
自己用oracle的正则替换一下就行了,然后外层加一个select判断是否大于20
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
还是不建议这样做,太耗性能了,尽量在程序实现; 实在不行,写oracle的function吧,这个真的不行,虽然实现目的,但是其性能,哎。
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
为了你这个问题,我还真是想了很久,首先分享一个观点吧: oracle对正则支持很浅,建议不使用在oracle中使用正则表达式,因为容易造成low performance。由于你的条件比较多,我的sql也比较复杂,肯定我的有值得优化的地方,嘿嘿,新手路过。
 WITH TS AS
 (SELECT '1111,222,3312' A FROM DUAL UNION ALL
 SELECT '1,2,3,4,5,6' FROM  DUAL UNION ALL
 SELECT '66,77' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  )

 SELECT DISTINCT a,regexp_substr(a,'[[:alnum:]]+',1,level) t,LEVEL e
 from ts
    connect by level<=length(regexp_replace(a,'[[:alnum:]]+'))+1
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
哦,在注释中忘了说了,函数对你的需求没有任何问题,只是拓展性很差。 是使用正则表达式判断进行拆分这里说了一句,有缺陷,但由于使用了if条件判断,所以没有任何问题,大可拿去测试。
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
亲,都是我一个人在回复,我把sql丢给你吧,写了我半个小时
--函数只是用于判断是否纯数字以及带符号的
CREATE OR REPLACE FUNCTION ONERE_TO_MANYRE(VALUE1 IN VARCHAR2,--这个是字符串
                                           SYMBOL IN CHAR) RETURN VARCHAR2 IS--这个是你的判断字符,在你的需求里面是分号
    RESULT      VARCHAR2(100);
    STRING_NUM1 NUMBER;
    STRING_NUM2 NUMBER;
    Number_flag CHAR(1);
    reg_exp     NVARCHAR2(100);
BEGIN
    reg_exp := '^[1-9][0-9]*(' || SYMBOL || '[0-9]*)*';
    SELECT COUNT(CASE LENGTH(REGEXP_SUBSTR(a, reg_exp))
                     WHEN LENGTH(A) THEN
                      a
                 END) B
      INTO Number_flag
      FROM (SELECT VALUE1 a FROM dual);
    IF Number_flag = 0 THEN
        RESULT := '存在非数字';
    ELSIF Number_flag = 1 THEN
    
        --这是使用正则表达式判断进行拆分(注:这个有缺陷)
        SELECT COUNT(*)
          INTO STRING_NUM2
          FROM (sELECT DISTINCT regexp_substr(a, '[[:digit:]]+', 1, level) t
                  from (SELECT VALUE1 a FROM DUAL)
                connect by level <=
                           length(regexp_replace(a, '[[:digit:]]+')))
         WHERE length(t) >= 20;
    
        IF STRING_NUM2 >= 1 THEN
            RESULT := '存在超过20个字符的子字符';
        ELSE
            RESULT := '有效字符';
        END IF;
    END IF;
    /* --未使用正则表达式对源字符进行拆分并判断,不建议使用这个
    SELECT COUNT(*)
      INTO STRING_NUM1
      FROM (SELECT SUBSTR(SYMBOL || A.STR || SYMBOL,
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) + 1,
                          INSTR(SYMBOL || A.STR || SYMBOL,
                                SYMBOL,
                                1,
                                ROWNUM + 1) -
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) - 1) T
              FROM (SELECT VALUE1 STR FROM DUAL) A, ALL_OBJECTS
             WHERE ROWNUM <
                   LENGTH(SYMBOL || A.STR || SYMBOL) -
                   LENGTH(REPLACE(SYMBOL || A.STR || SYMBOL, SYMBOL)))
     WHERE LENGTH(T) >= 20;
    
    IF STRING_NUM1 >= 1 THEN
        RESULT := '存在超过20个字符的子字符';
    END IF;*/
    RETURN(RESULT);
END ONERE_TO_MANYRE;

17,140

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧