PLSQL显示字符串

时间:2015-06-28 11:24:21

标签: sql regex oracle plsql regexp-substr

我有以下问题。 有一个字符串:

There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235

我只需要显示此字符串中的最后一个日期:2015.06.07。 我尝试使用regexp_substr insrt,但它不起作用。 所以这只是测试,如果我能用这个解决方案解决这个问题,我应该将它用于CLOB查询,其中有多个日期,我只需要最后一个。我知道有regexp_count,这有助于解决这个问题,但我使用的数据库是Oracle 10g,所以它不会工作。

有人能帮助我吗?

4 个答案:

答案 0 :(得分:2)

找到此问题解决方案的关键是颠倒this answer中显示的字符串中的单词。

以下是可能的解决方案:

WITH words AS
(
SELECT regexp_substr(str, '[^[:space:]]+', 1, LEVEL) word, 
        rownum rn
   FROM (SELECT 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 2015.06.08 2015.06.17. 2015.07.01. 12345678999 12125235' str
           FROM dual) tab
CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1
)
, words_reversed AS 
(
SELECT *
  FROM words
 ORDER BY rn DESC
)
SELECT regexp_substr(word, '\d{4}\.\d{2}\.\d{2}', 1, 1)
  FROM words_reversed
 WHERE regexp_like(word, '\d{4}\.\d{2}\.\d{2}')
   AND rownum = 1;

答案 1 :(得分:1)

regexp_substr上的文档中,我立即看到了一个问题:

.(句点)匹配任何字符。你需要使用反斜杠\.来逃避它们,以便只匹配一个句号字符。

作为参考,我正在关联this post,这似乎是您使用substrinstr所采用的方法。

来自Oracle的

Relevant documentation

INSTR(string , substring [, position [, occurrence]])

  

当position为负数时,INSTR会计算并从字符串末尾向后搜索。 position的默认值为1,这意味着该函数开始在字符串的开头搜索。

这里的问题是你的正则表达式只返回一个值,如here所述,因此在多个日期的情况下,你将为instr函数提供适当的匹配。

现在,由于这个限制,我建议使用this question中提出的方法,即反转整个字符串(和你的正则表达式,即\d{2}\.\d{2}\.\d{4}),然后第一个匹配将是'最后一场比赛'。然后,执行另一个字符串反转以获取原始日期格式。

也许这不是最佳解决方案,但它应该有效。

答案 2 :(得分:1)

有三种不同的PL / SQL函数可以帮助您。

  1. INSTR函数将识别日期字符串中第一个“句点”的出现位置。
  2. SUBSTR使用(1)中的值作为起点
  3. 应用于整个字符串
  4. TO_DATE针对特定日期掩码:YYYY.MM.DD会将结果从(2)转换为Oracle日期时间类型。
  5. 要在程序代码中使用,标准块适用:

     DECLARE
        v_position pls_integer;
        ... other variables
     BEGIN
        sql code and function calls;
    
     END
    

    SQL Fiddle

    Oracle 11g R2架构设置

    CREATE TABLE finddate
        (column1 varchar2(11), column2 varchar2(39))
    ;
    
    INSERT ALL 
        INTO finddate (column1, column2)
             VALUES ('row1', '1234567 242424 2015.06.07. 12125235')
        INTO finddate (column1, column2)
             VALUES ('string2', '1234567 242424 2015.06.07. 12125235')
    SELECT * FROM dual
    ;
    

    查询1

    select instr(column2,'.',1) from finddate
    where column1 = 'string2'
    
    select substr(column2,(20-4),10) from finddate
    
    select to_date('2015.06.07','YYYY.MM.DD') from finddate
    

    <强> Results

    | TO_DATE('2015.06.07','YYYY.MM.DD') |
    |------------------------------------|
    |             June, 07 2015 00:00:00 |
    |             June, 07 2015 00:00:00 |
    

答案 3 :(得分:1)

使用regexp_replace()的方法可以使用10g,假设行的格式相同:

with tbl(col_string) as
(
  select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235' 
  from dual
)
select regexp_replace(col_string, '^.*(\d{4}\.\d{2}\.\d{2})\. \d*$', '\1')
from tbl;

正则表达式可以理解为:

^   - Match the start of the line
.   - followed by any character
*   - followed by 0 or more of the previous character (which is any character)
(   - Start a remembered group
\d{4}\.\d{2}\.\d{2} - 4 digits followed by a literal period followed by 2 digits, etc
)   - End the first remembered group
\.  - followed by a literal period
    - followed by a space
\d* - followed by any number of digits
$   - followed by the end of the line
然后,

regexp_replace将所有内容替换为第一个记住的组(\ 1)。

基本上将整行描述为正则表达式,围绕您想要返回的内容进行分组。如果它可能是除了数字之外的其他字符,你很可能需要在行尾调整正则表达式,但这应该给你一个想法。

为了论证,这也有效仅在时出现2次日期模式:

with tbl(col_string) as
(
  select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235' from dual
)
select regexp_substr(col_string, '\d{4}\.\d{2}\.\d{2}', 1, 2)
from tbl;

返回第二次出现的模式。我希望上面的regexp_replace能更准确地描述解决方案。