我注意到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;
答案 0 :(得分:2)
如果您使用的是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: