Estoy tratando de configurar mis scripts sql en una transacción para lograr atomicidad con mi base de datos.
La estructura de la tabla es (simplificada):
CREATE TABLE foo ( id serial NOT NULL, foo varchar(50) NOT NULL, CONSTRAINT foo_pk PRIMARY KEY (id) ); CREATE TABLE access ( id serial NOT NULL, foo_id int NULL CONSTRAINT access_pk PRIMARY KEY (id) ); ALTER TABLE access ADD CONSTRAINT access_foo FOREIGN KEY (foo_id) REFERENCES foo (id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED; En mi código primero declaro: client.query('BEGIN'); (Estoy usando la biblioteca npm 'pg') luego inserte una fila en una tabla 'foo', luego otra inserción para 'acceder' con un foo_id desde la primera inserción. Después de eso está client.query('COMMIT');
Todo esto está en un try catch, y en el catch está client.query('ROLLBACK'); y el retroceso parece estar funcionando si hay un problema con cualquiera de las inserciones. Cuando todo debería estar comprometido, todavía termino en el bloque catch para esto:
mensaje: "insertar o actualizar en la tabla "acceso" viola la restricción de clave externa "access_foo""
detalle: "La clave (foo_id)=(20) no está presente en la tabla "foo"."
Pensé que aplazar la restricción sería suficiente para hacer esto, pero supongo que estoy equivocado. Cualquier ayuda es bienvenida.
Probablemente tenga algún problema con la demarcación de la transacción. Hice una prueba simple y funciona bien.
insert into foo (id, foo) values (1, 'Anne'); start transaction; insert into access (id, foo_id) values (101, 1); insert into access (id, foo_id) values (107, 7); -- 7 does not exist yet... insert into foo (id, foo) values (7, 'Ivan'); -- 7 now exists! commit; -- at this point all is goodVer ejemplo de ejecución en DB Fiddle .