我注意到 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/