错误和诊断
ASSERT
ASSERT 是一个调试功能,它可以检查某个条件是否为 true
。如果条件为 false
,则 ASSERT 引发 ASSERT_FAILURE
异常,并显示可选错误消息。
要转义 '
(单引号)字符,请使用 ''
。同样,要转义 "
(双引号)字符,请使用 ""
。
ASSERT condition [ , message ];
例如,此过程检查 products
表中的行数,并使用 ASSERT 检查是否填充了该表。如果该表为空,则 Vertica 引发错误:
=> CREATE TABLE products(id UUID, name VARCHARE, price MONEY);
CREATE TABLE
=> SELECT * FROM products;
id | name | price
----+------+-------
(0 rows)
DO $$
DECLARE
prod_count INT;
BEGIN
prod_count := SELECT count(*) FROM products;
ASSERT prod_count > 0, 'products table is empty';
END;
$$;
ERROR 2005: products table is empty
要让 Vertica 停止检查 ASSERT 语句,您可以设置布尔会话级别参数PLpgSQLCheckAsserts
。
RAISE
RAISE 可以引发错误或输出用户指定的下列错误消息之一:
RAISE [ level ] 'format' [, arg_expression [, ... ]] [ USING option = expression [, ... ] ];
RAISE [ level ] condition_name [ USING option = expression [, ... ] ];
RAISE [ level ] SQLSTATE 'sql-state' [ USING option = expression [, ... ] ];
RAISE [ level ] USING option = expression [, ... ];
此过程演示各种 RAISE 级别:
=> DO $$
DECLARE
logfile varchar := 'vertica.log';
BEGIN
RAISE LOG 'this message was sent to %', logfile;
RAISE INFO 'info';
RAISE NOTICE 'notice';
RAISE WARNING 'warning';
RAISE EXCEPTION 'exception';
RAISE NOTICE 'exception changes control flow; this is not printed';
END;
$$;
INFO 2005: info
NOTICE 2005: notice
WARNING 2005: warning
ERROR 2005: exception
$ grep 'this message was sent to vertica.log' v_vmart_node0001_catalog/vertica.log
<LOG> @v_vmart_node0001: V0002/2005: this message is sent to vertica.log
异常
EXCEPTION 块使您可以捕获和处理从 statements 引发的异常:
[ <<label>> ]
[ DECLARE
declarations ]
BEGIN
statements
EXCEPTION
WHEN exception_condition [ OR exception_condition ... ] THEN
handler_statements
[ WHEN exception_condition [ OR exception_condition ... ] THEN
handler_statements
... ]
END [ label ];
exception_condition 具有下列格式之一:
WHEN errcode_division_by_zero THEN ...
WHEN division_by_zero THEN ...
WHEN SQLSTATE '22012' THEN ...
WHEN OTHERS THEN ...
OTHERS 是特殊条件,它捕获除 QUERY_CANCELLED
、ASSERT_FAILURE
和 FEATURE_NOT_SUPPORTED
之外的所有异常。
当引发异常时,Vertica 检查异常列表,从上到下查找匹配的 exception_condition。如果找到匹配,它将执行 handler_statements,然后离开异常块范围。
如果 Vertica 找不到匹配,则会将异常传播到下一个封闭块。您可以使用 RAISE 在异常处理程序中手动执行此操作:
RAISE;
例如,以下过程在 inner_block
中用 3 除以 0,这是一个非法操作,将引发 division_by_zero
异常(SQL 状态 22012)。Vertica 检查内部 EXCEPTION 块以查找匹配的条件:
-
第一个条件检查 SQL 状态 42501,因此 Vertica 移动到下一个条件。
-
WHEN OTHERS THEN 捕获所有异常,因此它执行该块。
-
随后,基本 RAISE 将异常传播到
outer_block
。 -
外部 EXCEPTION 块成功捕获异常并输出消息。
=> DO $$
<<outer_block>>
BEGIN
<<inner_block>>
DECLARE
x int;
BEGIN
x := 3 / 0; -- throws exception division_by_zero, SQLSTATE 22012
EXCEPTION -- this block is checked first for matching exceptions
WHEN SQLSTATE '42501' THEN
RAISE NOTICE 'caught insufficient_privilege exception';
WHEN OTHERS THEN -- catches all exceptions
RAISE; -- manually propagate the exception to the next enclosing block
END inner_block;
EXCEPTION -- exception is propagated to this block
WHEN division_by_zero THEN
RAISE NOTICE 'caught division_by_zero exception';
END outer_block;
$$;
NOTICE 2005: caught division_by_zero exception
SQLSTATE 和 SQLERRM 变量
当处理异常时,您可以使用以下变量检索错误信息:
-
SQLSTATE
包含 SQL 状态 -
SQLERRM
包含错误消息
有关详细信息,请参阅SQL 状态列表。
此过程通过尝试将 NULL 赋值给 NOT NULL 变量捕获引发的异常,并输出 SQL 状态和错误消息:
DO $$
DECLARE
i int NOT NULL := 1;
BEGIN
i := NULL; -- illegal, i was declared with NOT NULL
EXCEPTION
WHEN OTHERS THEN
RAISE WARNING 'SQL State: %', SQLSTATE;
RAISE WARNING 'Error message: %', SQLERRM;
END;
$$;
WARNING 2005: SQLSTATE: 42809
WARNING 2005: SQLERRM: Cannot assign null into NOT NULL variable
检索异常信息
您可以使用 GET STACKED DIAGNOSTICS 在异常处理程序中检索有关异常的信息:
GET STACKED DIAGNOSTICS variable_name { = | := } item [, ... ];
其中 item 可以是以下任意一项:
例如,此过程有一个 EXCEPTION 块,它捕捉 division_by_zero
错误并输出 SQL 状态、错误消息和异常上下文:
=> DO $$
DECLARE
message_1 varchar;
message_2 varchar;
message_3 varchar;
x int;
BEGIN
x := 5 / 0;
EXCEPTION
WHEN OTHERS THEN -- OTHERS catches all exceptions
GET STACKED DIAGNOSTICS message_1 = RETURNED_SQLSTATE,
message_2 = MESSAGE_TEXT,
message_3 = EXCEPTION_CONTEXT;
RAISE INFO 'SQLSTATE: %', message_1;
RAISE INFO 'MESSAGE: %', message_2;
RAISE INFO 'EXCEPTION_CONTEXT: %', message_3;
END;
$$;
INFO 2005: SQLSTATE: 22012
INFO 2005: MESSAGE: Division by zero
INFO 2005: EXCEPTION_CONTEXT: PL/vSQL procedure inline_code_block line 8 at static SQL