【问题标题】:How to find a specific mask within a string - Oracle?如何在字符串中查找特定掩码 - Oracle?
【发布时间】:2023-03-29 09:36:01
【问题描述】:

我在表中有一个字段,可以用不同的值通知。 示例:

Row 1 - (2012,2013) 
Row 2 - 8871 
Row 3 - 01/04/2012 
Row 4 - 'NULL' 

我必须识别具有通知日期掩码“dd/mm/yyyy”的字符串的行。和第 3 行一样,所以我可以添加一个 TO_DATE 函数。

知道如何在该字段中搜索掩码吗?

非常感谢

【问题讨论】:

标签: string oracle date mask to-date


【解决方案1】:

听起来像是数据模型问题(将日期存储在字符串中)。

但是,既然它发生了,我们有时无法控制或改变事情,我通常会保留一个这样的函数:

CREATE OR REPLACE FUNCTION safe_to_date (p_string        IN VARCHAR2,
                                         p_format_mask   IN VARCHAR2,
                                         p_error_date    IN DATE DEFAULT NULL)
  RETURN DATE
  DETERMINISTIC IS
  x_date   DATE;
BEGIN
  BEGIN
    x_date   := TO_DATE (p_string, p_format_mask);
    RETURN x_date;                                                        -- Only gets here if conversion was successful
  EXCEPTION
    WHEN OTHERS THEN
      RETURN p_error_date;
  END;
END safe_to_date;

然后像这样使用它:

WITH d AS
       (SELECT 'X' string_field FROM DUAL
        UNION ALL
        SELECT '11/15/2012' FROM DUAL
        UNION ALL
        SELECT '155' FROM DUAL)
SELECT safe_to_date (d.string_field, 'MM/DD/YYYY')
FROM   d;

【讨论】:

  • 你能在你的 ddl 中添加CREATE OR REPLACE 以便它可以独立(而不是在一个包中)吗?另外,至少,删除 END LOOP; => 块不正确。
【解决方案2】:

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE Test ( id, VALUE ) AS
          SELECT 'Row 1', '(2012,2013)' FROM DUAL
UNION ALL SELECT 'Row 2', '8871' FROM DUAL
UNION ALL SELECT 'Row 3', '01/04/2012' FROM DUAL
UNION ALL SELECT 'Row 4', NULL FROM DUAL
UNION ALL SELECT 'Row 5', '99,99,2015' FROM DUAL
UNION ALL SELECT 'Row 6', '32/12/2015' FROM DUAL
UNION ALL SELECT 'Row 7', '29/02/2015' FROM DUAL
UNION ALL SELECT 'Row 8', '29/02/2016' FROM DUAL
/

查询 1 - 您可以使用正则表达式进行检查

SELECT *
FROM   TEST
WHERE  REGEXP_LIKE( VALUE, '^\d{2}/\d{2}/\d{4}$' )

Results

|    ID |      VALUE |
|-------|------------|
| Row 3 | 01/04/2012 |
| Row 6 | 32/12/2015 |
| Row 7 | 29/02/2015 |
| Row 8 | 29/02/2016 |

查询 2 - 您可以使正则表达式更复杂以捕获更多无效日期

SELECT *
FROM   TEST
WHERE  REGEXP_LIKE( VALUE, '^(0[1-9]|[12]\d|3[01])/(0[1-9]|1[0-2])/\d{4}$' )

Results

|    ID |      VALUE |
|-------|------------|
| Row 3 | 01/04/2012 |
| Row 7 | 29/02/2015 |
| Row 8 | 29/02/2016 |

查询 3 - 但最好的方法是尝试将值转换为日期,看看是否有异常

CREATE OR REPLACE FUNCTION is_Valid_Date(
  datestr VARCHAR2,
  format  VARCHAR2 DEFAULT 'DD/MM/YYYY'
) RETURN NUMBER DETERMINISTIC
AS
  x DATE;
BEGIN
  IF datestr IS NULL THEN
    RETURN 0;
  END IF;
  x := TO_DATE( datestr, format );
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    RETURN 0;
END;
/


SELECT *
FROM   TEST
WHERE  is_Valid_Date( VALUE ) = 1

Results

|    ID |      VALUE |
|-------|------------|
| Row 3 | 01/04/2012 |
| Row 8 | 29/02/2016 |

【讨论】:

  • 我也偏爱正则表达式。这样做的失败是错误的,例如99,99,2015。根据操作的要求,这将导致误报。
【解决方案3】:

你可以使用like运算符来匹配模式。

where possible_date_field like '__/__/____';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-03
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多