oracle - 如何在不使用 OTHERS 子句的情况下捕获 PLSQL 中的 TO_TIMESTAMP 或 TO_DATE 异常?

标签 oracle plsql

我注意到 TO_TIMESTAMP 会根据失败的原因引发各种错误代码;

--01847
select to_timestamp('2016-01-0a', 'yyyy-MM-dd') from dual;
--01858
select to_timestamp('2016-01-aa', 'yyyy-MM-dd') from dual;
--01843
select to_timestamp('2016-15-01', 'yyyy-MM-dd') from dual;

鉴于它不会引发单个错误代码,我如何才能捕获错误而不诉诸使用包罗万象的OTHERS:

DECLARE
    foo timestamp;
BEGIN
    select to_timestamp('2016-01-0a', 'yyyy-MM-dd') into foo from dual;
EXCEPTION
    WHEN OTHERS THEN
        dbms_output.put_line('bad date');
END;

最佳答案

如果您使用的是 12cR2,则可以在进行转换之前使用 VALIDATE_CONVERSION 检查潜在类型转换的有效性,并完全避免异常。

在早期版本中,您可以为 TIMESTAMP 创建自己的等效函数来尝试转换并处理异常。您可以单独声明每个感兴趣的异常类型,并根据需要分别记录/处理每个感兴趣的故障模式,并为您不关心或不想要的内容提供总体的 WHEN OTHERS日志/句柄:

CREATE OR REPLACE FUNCTION IS_TIMESTAMP_FORMAT_OK(P_TIMESTAMP_TEXT IN VARCHAR2, P_FORMAT IN VARCHAR2 DEFAULT 'yyyy-MM-dd')
  RETURN BOOLEAN
IS
  --exception names
  V_TIMESTAMP TIMESTAMP;
    DAY_OF_MONTH EXCEPTION;
    NON_NUMERIC EXCEPTION;
  --etc.
PRAGMA EXCEPTION_INIT (DAY_OF_MONTH, -1847);
PRAGMA EXCEPTION_INIT (NON_NUMERIC, -1858);
  BEGIN
    V_TIMESTAMP := to_timestamp(P_TIMESTAMP_TEXT, P_FORMAT);
    RETURN TRUE;
    EXCEPTION WHEN DAY_OF_MONTH
    THEN
    DBMS_OUTPUT.PUT_LINE('The day of month must be between...');
    RETURN FALSE;
    WHEN NON_NUMERIC
    THEN
    DBMS_OUTPUT.PUT_LINE('Non-Numeric data was found...');
    RETURN FALSE;
    --etc.
    WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(UTL_LMS.FORMAT_MESSAGE('Unexpected timestamp problem: %s', SQLERRM));
    RETURN FALSE;
  END;
/

然后您可以记录/处理感兴趣的类型:

DECLARE
  V_CHECK BOOLEAN;
BEGIN
  V_CHECK := IS_TIMESTAMP_FORMAT_OK('2016010a');
  V_CHECK := IS_TIMESTAMP_FORMAT_OK('2016-01-aa');
  V_CHECK := IS_TIMESTAMP_FORMAT_OK('2016-01-0a');
  IF IS_TIMESTAMP_FORMAT_OK('2014-01-01')
  THEN
    DBMS_OUTPUT.PUT_LINE('It is ok.  Yay');
  END IF;
END;
/

Unexpected timestamp problem: ORA-01862: the numeric value does not match the
length of the format item
Non-Numeric data was found...
The day of month must be between...
It is ok.  Yay

或者,如果您不关心日志记录/处理不同的故障模式,而只是想防止广泛的异常捕获,则可以继续使用WHEN OTHERS,但在隔离范围内:

CREATE OR REPLACE FUNCTION 
  IS_TIMESTAMP_FORMAT_OK(P_TIMESTAMP_TEXT IN VARCHAR2, P_FORMAT IN VARCHAR2 DEFAULT 'yyyy-MM-dd')
  RETURN BOOLEAN
IS
  V_TIMESTAMP TIMESTAMP;
  BEGIN
    V_TIMESTAMP := to_timestamp(P_TIMESTAMP_TEXT, P_FORMAT);
    RETURN TRUE;
    EXCEPTION WHEN OTHERS THEN
    RETURN FALSE;
  END;
/

或内联:

DECLARE
  V_MY_TIMESTAMP TIMESTAMP;
  BEGIN
  -- some other code ...

  BEGIN
    V_MY_TIMESTAMP := to_timestamp('2016-01-aa', 'yyyy-MM-dd');
    EXCEPTION WHEN OTHERS THEN NULL;
  END;

  DBMS_OUTPUT.PUT_LINE('My Timestamp:'||V_MY_TIMESTAMP);

END;
/

My Timestamp:

关于oracle - 如何在不使用 OTHERS 子句的情况下捕获 PLSQL 中的 TO_TIMESTAMP 或 TO_DATE 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43530586/

相关文章:

sql - 连接多个表 - Oracle

sql - 什么是儒略日期格式

oracle - 我有一个 SQL 脚本

java - Java 中的准备语句连接

oracle - 如何将oracle toad中的存储过程保存到脚本文件

php-oci8编码问题

c# - 从 Oracle 读取问题

oracle - 用于设计的 Lotus Notes XPage 和用于数据的 Oracle(或其他 RDBMS)

Oracle PL/SQL - 如何创建简单的数组变量?

sql - 使用光标输入时包未执行