2 votes

Comment transformer un sql en une transaction avec plusieurs déclarations ?

J'ai ce sql que j'exécute en php en utilisant pg_query_params. Cependant, si j'essaie de le transformer en transaction avec BEGIN ; et COMMIT ; j'obtiens l'erreur suivante : Query failed: ERROR: cannot insert multiple commands into a prepared statement

Est-il possible de préparer une transaction avec plusieurs déclarations dans la même requête ? Ou comment dois-je la modifier pour préparer une transaction ?

Merci !

WITH usr1 AS (
         SELECT id FROM users WHERE mongoid = $1
     ),
     usr2 AS (
         INSERT INTO users (mongoid, shopid, idinshop, attributes)
           SELECT $1, $2, $3, $4
           WHERE  NOT EXISTS (SELECT 1 FROM usr1)
           RETURNING id
     ),
     ses1 AS (
         UPDATE sessions 
           SET traffic=$7, counts=$8 
           WHERE mongoid=$5 
           RETURNING id
     ),
     ses2 AS (
         INSERT INTO sessions (mongoid, shopid, userid, session, traffic, counts)
           SELECT $5, $2, (SELECT id FROM usr1 NATURAL FULL OUTER JOIN usr2),
                  $6, $7, $8
             WHERE  NOT EXISTS (SELECT 1 FROM ses1)
         RETURNING id
     )

INSERT INTO events (shopid, sessionid, userid, type, attributes, mongoid) 
  VALUES (
      $2,
      (SELECT id FROM usr1 NATURAL FULL OUTER JOIN usr2),
      (SELECT id FROM ses1 NATURAL FULL OUTER JOIN ses2),
      $9, $10, $11
);

Et puis je cours : pg_query_params($db, $sql, array(...))

1voto

Clodoaldo Neto Points 26723

Vous n'avez pas besoin d'un begin/commit bloc. Cette déclaration entière est une transaction en soi

create table t (id int primary key);

with s as (
    insert into t values (1) 
    returning id
)
insert into t (id)
select id from s
;
ERROR:  duplicate key value violates unique constraint "t_pkey"
DETAIL:  Key (id)=(1) already exists.

Le CTE ( with... ) a été annulé :

select * from t;
 id 
----
(0 rows)

http://sqlfiddle.com/#!12/0eeef/2

De la manuel :

PostgreSQL traite en fait chaque instruction SQL comme étant exécutée dans une transaction. Si vous n'émettez pas de commande BEGIN, chaque instruction individuelle est entourée d'un BEGIN implicite et d'un COMMIT (en cas de succès).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X