我是PostgreSQL的新手。任何人都可以更正此查询。
BEGIN TRANSACTION;
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
);
COMMIT TRANSACTION;
RAISE NOTICE 'Task completed sucessfully.'
EXCEPTION;
ROLLBACK TRANSACTION;
RAISE ERROR @ErrorMessage, @LineNumber, @ErrorState --how to catch errors and display them????
END;
问题:
答案 0 :(得分:62)
捕获错误消息及其代码:
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';
尚未找到行号
更新2019年4月16日
根据Diego Scaravaggi的建议,对于Postgres 9.2及以上版本,请使用GET STACKED DIAGNOSTICS:
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; $$;
结果:
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
除GET STACKED DIAGNOSTICS
符合SQL标准外,其诊断变量(例如message_text
)仅与GSD相关。因此,如果您的表中有一个名为message_text
的字段,则GSD不可能干扰您的字段值。
但仍然没有行号。
答案 1 :(得分:13)
使用版本9.0中的新选项DO statement:
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;
$$;
答案 2 :(得分:3)
您可以将其写为psql脚本,例如
START TRANSACTION;
CREATE TABLE ...
CREATE TABLE ...
COMMIT;
\echo 'Task completed sucessfully.'
并使用
运行psql -f somefile.sql
直接在PostgreSQL中无法使用参数引发错误。在移植此类代码时,有些人会在错误字符串中编码必要的信息,并在必要时将其解析出来。
这一切都有所不同,所以要准备好重新学习/重新思考/重写很多东西。
答案 3 :(得分:0)
只想在这个旧帖子上加上我的两分钱:
我认为,即使您具有autocommit = false,几乎所有关系数据库引擎在执行DDL命令后都会自动包括落实提交事务,因此您无需启动事务来避免潜在的被截断的对象创建,因为完全没有必要。