Solución:
Para captar el mensaje de error y su código:
do $$
begin
create table yyy(a int);
create table yyy(a int); -- this will cause an error
exception when others then
raise notice 'The transaction is in an uncommittable state. '
'Transaction was rolled back';
raise notice '% %', SQLERRM, SQLSTATE;
end; $$
language 'plpgsql';
Aún no he encontrado el número de línea
ACTUALIZACIÓN 16 de abril de 2019
Como sugirió Diego Scaravaggi, para Postgres 9.2 y versiones posteriores, use OBTENER DIAGNÓSTICOS APILADOS:
do language plpgsql $$
declare
v_state TEXT;
v_msg TEXT;
v_detail TEXT;
v_hint TEXT;
v_context TEXT;
begin
create table yyy(a int);
create table yyy(a int); -- this will cause an error
exception when others then
get stacked diagnostics
v_state = returned_sqlstate,
v_msg = message_text,
v_detail = pg_exception_detail,
v_hint = pg_exception_hint,
v_context = pg_exception_context;
raise notice E'Got exception:
state : %
message: %
detail : %
hint : %
context: %', v_state, v_msg, v_detail, v_hint, v_context;
raise notice E'Got exception:
SQLSTATE: %
SQLERRM: %', SQLSTATE, SQLERRM;
raise notice '%', message_text; -- invalid. message_text is contextual to GET STACKED DIAGNOSTICS only
end; $$;
Resultado:
NOTICE: Got exception:
state : 42P07
message: relation "yyy" already exists
detail :
hint :
context: SQL statement "create table yyy(a int)"
PL/pgSQL function inline_code_block line 11 at SQL statement
NOTICE: Got exception:
SQLSTATE: 42P07
SQLERRM: relation "yyy" already exists
ERROR: column "message_text" does not exist
LINE 1: SELECT message_text
^
QUERY: SELECT message_text
CONTEXT: PL/pgSQL function inline_code_block line 33 at RAISE
SQL state: 42703
Aparte de GET STACKED DIAGNOSTICS
es compatible con el estándar SQL, sus variables de diagnóstico (p. ej., message_text
) son contextuales solo para GSD. Entonces, si tiene un campo llamado message_text
en su tabla, no hay posibilidad de que GSD pueda interferir con el valor de su campo.
Sin embargo, todavía no hay número de línea.
Utilice la declaración DO, una nueva opción en la versión 9.0:
DO LANGUAGE plpgsql
$$
BEGIN
CREATE TABLE "Logs"."Events"
(
EventId BIGSERIAL NOT NULL PRIMARY KEY,
PrimaryKeyId bigint NOT NULL,
EventDateTime date NOT NULL DEFAULT(now()),
Action varchar(12) NOT NULL,
UserId integer NOT NULL REFERENCES "Office"."Users"(UserId),
PrincipalUserId varchar(50) NOT NULL DEFAULT(user)
);
CREATE TABLE "Logs"."EventDetails"
(
EventDetailId BIGSERIAL NOT NULL PRIMARY KEY,
EventId bigint NOT NULL REFERENCES "Logs"."Events"(EventId),
Resource varchar(64) NOT NULL,
OldVal varchar(4000) NOT NULL,
NewVal varchar(4000) NOT NULL
);
RAISE NOTICE 'Task completed sucessfully.';
END;
$$;
Puede escribir esto como un script psql, por ejemplo,
START TRANSACTION;
CREATE TABLE ...
CREATE TABLE ...
COMMIT;
echo 'Task completed sucessfully.'
y corre con
psql -f somefile.sql
No es posible generar errores con parámetros en PostgreSQL directamente. Al portar dicho código, algunas personas codifican la información necesaria en la cadena de error y la analizan si es necesario.
Todo funciona de manera un poco diferente, así que prepárate para volver a aprender / repensar / reescribir muchas cosas.