PostgreSQL - Problema con una transacción - exception

 
Vista:

Problema con una transacción - exception

Publicado por Gabriel (1 intervención) el 26/02/2021 20:09:46
Buenas tardes,

Estoy tratando de crear un procedimiento para controlar una transacción pero obtengo un error que no sé resolver:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
drop table if exists cuentas;
 
create table cuentas (
    id serial,
    nombre varchar(100) not null,
    saldo dec(15,2) not null,
    primary key(id),
    constraint saldo CHECK(saldo > 5000)
);
 
 
insert into cuentas(nombre, saldo)
values('Carlos',10000);
 
insert into cuentas(nombre, saldo)
values('Cesar',10000);
 
SELECT * FROM cuentas;
 
drop procedure if exists transferir;
 
create or replace procedure transferir(id_emisor int,id_receptor int,cantidad dec)
language plpgsql
as $$
begin
-- adding the amount from the recievers's account
update cuentas
set saldo = saldo + cantidad
where id = id_receptor;
-- substracting the amount to the sender's account
update cuentas
set saldo = saldo - cantidad
where id = id_emisor;
commit;
 
EXCEPTION
    WHEN check_violation THEN
        RAISE NOTICE 'Violación de saldo.';
        rollback;
        commit;
end;$$

Cuando trato de ejecutar:

1
call transferir(1,2,1000);

Obtengo el siguiente error:

1
2
3
ERROR:  no se puede comprometer mientras hay una subtransacción activa
CONTEXT:  función PL/pgSQL transferir(integer,integer,numeric) en la línea 13 en COMMIT
Estado SQL: 2D000

¿Alguien puede ayudarme?

Muchas gracias.

Saludos
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de Francisco
Val: 256
Oro
Ha mantenido su posición en PostgreSQL (en relación al último mes)
Gráfica de PostgreSQL

Problema con una transacción - exception

Publicado por Francisco (110 intervenciones) el 13/03/2021 20:44:25
Hola

El problema es que no puedes usar COMMIT O ROLLBACK en funciones y procedures ya que ambos están ejecutándose en una transacción, cuando ocurre un EXCEPTION Postgres automáticamente lanza un ROLLBACK;

https://stackoverflow.com/questions/63489949/how-to-roll-back-a-transaction-on-error-in-postgresql


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
DROP TABLE IF EXISTS cuentas;
CREATE TABLE cuentas (
  id serial,
  nombre varchar(100) not null,
  saldo dec(15, 2) not null,
  PRIMARY KEY (id),
  CONSTRAINT saldo CHECK(saldo > 5000)
);
 
INSERT INTO cuentas(nombre, saldo) VALUES('Carlos', 10000);
INSERT INTO cuentas(nombre, saldo) VALUES('Cesar', 10000);
 
DROP PROCEDURE IF EXISTS transferir;
 
CREATE OR REPLACE PROCEDURE transferir(id_emisor int, id_receptor int, cantidad dec)
AS
$BODY$
DECLARE
	/*
    v_state   TEXT;
    v_msg     TEXT;
    v_detail  TEXT;
    v_hint    TEXT;
    v_context TEXT;
	*/
BEGIN
 
	-- adding the amount from the recievers s account
	UPDATE cuentas
		SET saldo = saldo + cantidad
	WHERE id = id_receptor;
 
	-- substracting the amount to the sender s account
	UPDATE cuentas
		SET saldo = saldo - cantidad
	WHERE id = id_emisor;
 
	RETURN;
 
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 EXCEPTION E'Got exception:
        state  : %
        message: %
        detail : %
        hint   : %
        context: %', v_state, v_msg, v_detail, v_hint, v_context;
	*/
 
	RAISE EXCEPTION 'Violación de saldo.';
 
END;
$BODY$
LANGUAGE plpgsql;
 
CALL transferir(1, 2, 6000);
 
SELECT * FROM  cuentas;

Saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar