2016-12-16 106 views
0

正如您所知,Oracle POSIX实现的正则表达式不支持单词边界。这里建议一个解决方法: Oracle REGEXP_LIKE and word boundariesOracle regexp_like单词边界多个单词解决方法

但是,如果我想要,例如选择全部4个字符的字符串,它不起作用。考虑到这一点,例如:

myvar:=regexp_substr('test test','(^|\s|\W)[\S]{4}($|\s|\W)') 

这显然只选择第一次出现。我不知道如何在Oracle世界中这样做,尽管通常它只是(\b)[\S]{4}(\b)。问题是,大多数woraround依赖于一些不存在的功能,如lookaround等。

回答

0
select xmlcast(xmlquery('for $token in ora:tokenize(concat(" ",$in)," ") 
       where string-length($token) = $size 
       return $token' passing 'test test' as "in", 4 as "size" returning content) as varchar2(2000)) word from dual; 

Xquery和FLWOR expresion。

concat(" ",$in) - 变通方法如果输入字符串为空或它只有1个匹配字。

ora:tokenize - 由 “空间”

string-length($token) = $size检查,如果令牌有适当的长度标记化的字符串。

xmlcast - XMLType的转换为VARCHAR2

容易吗?如有任何问题:)

+0

我已经看到了许多使用Oracle XML的精彩解决方案,但我对此完全无知。有人可以推荐一本书或网站让我开始? –

0
DECLARE 
    str  VARCHAR2(200) := 'test test'; 
    pattern VARCHAR2(200) := '(\w+)($|\s+|\W+)'; 
    match VARCHAR2(200); 
BEGIN 
    FOR i IN 1 .. REGEXP_COUNT(str, pattern) LOOP 
    match := REGEXP_SUBSTR(str, pattern, 1, i, NULL, 1); 
    IF LENGTH(match) = 4 THEN 
     DBMS_OUTPUT.PUT_LINE(match); 
    END IF; 
    END LOOP; 
END; 
/

或(不使用REGEXP_COUNT或在11g中引入的REGEXP_SUBSTR第6个参数):

DECLARE 
    str    VARCHAR2(200) := 'test test'; 
    pattern CONSTANT VARCHAR2(3) := '\w+'; 
    match   VARCHAR2(200); 
    i    NUMBER(4,0) := 1; 
BEGIN 
    match := REGEXP_SUBSTR(str, pattern, 1, i); 
    WHILE match IS NOT NULL LOOP 
    IF LENGTH(match) = 4 THEN 
     DBMS_OUTPUT.PUT_LINE(match); 
    END IF; 
    i  := i + 1; 
    match := REGEXP_SUBSTR(str, pattern, 1, i); 
    END LOOP; 
END; 
/

输出

test 
test 

如果你想要在SQL中使用它,您可以轻松地将其转换为流水线函数或返回集合的函数。

+0

非常感谢。不幸的是,我在10g和REGEXP_COUNT不可用。我认为他们在11g中介绍了它。 – Dimiter

+0

@Dimiter添加了(希望)Oracle 10g解决方案。 – MT0

+0

@MTO:非常感谢!非常感激! – Dimiter