Précédent   Forum du club des développeurs et IT Pro > Bases de données > PostgreSQL > Requêtes
Requêtes Forum d'entraide sur les requêtes SQL spécifiques à PostgreSQL, les triggers, les vues, etc.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 12/09/2012, 16h45   #1
Fred_34
Membre expérimenté
 
Homme Frédéric
Inscription : juin 2011
Messages : 442
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Localisation : France

Informations forums :
Inscription : juin 2011
Messages : 442
Points : 576
Points : 576
Par défaut UPSERT (MySQL -> PostgreSQL)

Bonjour,

J'ai cette requête ( MySQL) que j'aimerai écrire pour postgresql :
Code :
1
2
3
4
5
6
7
8
9
10
INSERT INTO test7(idTest7,test7Long,test7Int,test7Float,test7CharArray,test7Timestamp,test7Date) 
VALUES (72063769328484353,0,1,0.0,'','1970-01-01 00:00:00.0','1970-01-01'),
       (72063769328484354,0,2,0.0,'','1970-01-01 00:00:00.0','1970-01-01')
ON DUPLICATE KEY UPDATE 
	test7Long=VALUES(test7Long),
	test7Int=VALUES(test7Int),
	test7Float=VALUES(test7Float),
	test7CharArray=VALUES(test7CharArray),
	test7Timestamp=VALUES(test7Timestamp),
	test7Date=VALUES(test7Date)

En cherchant un peu sur le net, j'ai trouvé cette façon de faire :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
WITH new_values (idTest7,test7Long,test7Int,test7Float,test7CharArray,test7Timestamp,test7Date) AS (
  VALUES 
    (72063769328484353,0,3,0.0,'',CAST ('1970-01-01 00:00:00.0' AS timestamp),CAST ('1970-01-01' AS DATE)),
    (72063769328484354,0,2,0.0,'',CAST ('1970-01-01 00:00:00.0' AS timestamp),CAST ('1970-01-01' AS DATE)) 
),
upsert AS
( 
    UPDATE test7 
        SET test7Long = new_values.test7Long,
            test7Int = new_values.test7Int,
            test7Float = new_values.test7Float,
            test7CharArray = new_values.test7CharArray,
            test7Timestamp =new_values.test7Timestamp,
            test7Date = new_values.test7Date
    FROM new_values
    WHERE test7.idTest7 = new_values.idTest7
    RETURNING test7.*
)
INSERT INTO test7 (idTest7,test7Long,test7Int,test7Float,test7CharArray,test7Timestamp,test7Date)
SELECT idTest7,test7Long,test7Int,test7Float,test7CharArray,test7Timestamp,test7Date
FROM new_values
WHERE NOT EXISTS (SELECT 1 
                  FROM upsert
                  WHERE upsert.idTest7 = new_values.idTest7)
Est-ce une bonne façon de faire ?
Il y a t'il une meilleure façon de faire ?

Merci de votre aide.
Fred_34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/09/2012, 17h44   #2
punkoff
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 2 158
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 30
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 2 158
Points : 3 491
Points : 3 491
Bonjour,


Ce que vous tentez de faire est un MERGE.
Non supporté par Postgresql.

Donc c'est bien un upsert qu'il va falloir utiliser. (ou 2 requêtes ..)
punkoff est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/09/2012, 11h36   #3
Fred_34
Membre expérimenté
 
Homme Frédéric
Inscription : juin 2011
Messages : 442
Détails du profil
Informations personnelles :
Nom : Homme Frédéric
Localisation : France

Informations forums :
Inscription : juin 2011
Messages : 442
Points : 576
Points : 576
Citation:
Envoyé par punkoff Voir le message
Ce que vous tentez de faire est un MERGE.
MERGE, je l'ai utilisé avec plus ou moins de réussite sur Oracle :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
MERGE INTO test7 target
  USING (
    SELECT 72063788739723265 AS idTest7,0 AS test7Long,2 AS test7Int,0.0 AS test7Float,'' AS test7CharArray,CAST('01/01/1970 00:00:00,0' AS timestamp) AS test7Timestamp,CAST('01/01/1970' AS date) AS test7Date FROM DUAL
    UNION
    SELECT 72063788739723267 AS idTest7,0 AS test7Long,2 AS test7Int,0.0 AS test7Float,'' AS test7CharArray,CAST('01/01/1970 00:00:00,0' AS timestamp) AS test7Timestamp,CAST('01/01/1970' AS date) AS test7Date FROM DUAL
  )new_values
  ON (new_values.idTest7 = target.idTest7)
  WHEN  MATCHED
  THEN UPDATE SET   
			target.test7Long = new_values.test7Long,
			target.test7Int = new_values.test7Int,
			target.test7Float = new_values.test7Float,
			target.test7CharArray = new_values.test7CharArray,
			target.test7Timestamp = new_values.test7Timestamp,
			target.test7Date = new_values.test7Date
  WHEN NOT MATCHED
  THEN
      INSERT (idTest7,test7Long,test7Int,target.test7Float,test7CharArray,test7Timestamp,test7Date)
      VALUES (new_values.idTest7,new_values.test7Long,new_values.test7Int,new_values.test7Float,new_values.test7CharArray,new_values.test7Timestamp,new_values.test7Date);
Citation:
Envoyé par punkoff Voir le message
Donc c'est bien un upsert qu'il va falloir utiliser.
Dois-je comprendre qu'il y a une seule façon de faire un upsert ?
Fred_34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/09/2012, 11h50   #4
punkoff
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 2 158
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 30
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 2 158
Points : 3 491
Points : 3 491
Cette fonctionnalité est très mal documentée et l'utilisation d'une CTE pour arriver à faire un upsert me semble plus d'une solution de contournement qu'autre chose.


Bref, pour l'instant cette solution marche, mais c'est assez exotique.


J'utiliserai plutôt 2 requêtes que ce truc là personnellement.
punkoff est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 17h02.


 
 
 
 
Partenaires

Hébergement Web