Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 4 sur 4
  1. #1
    Membre expérimenté
    Homme Profil pro Frédéric
    Inscrit en
    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 : 550
    Points
    550

    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.

  2. #2
    Expert Confirmé Sénior
    Homme Profil pro
    Inscrit en
    mai 2002
    Messages
    3 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : mai 2002
    Messages : 3 037
    Points : 4 613
    Points
    4 613

    Par défaut

    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 ..)

  3. #3
    Membre expérimenté
    Homme Profil pro Frédéric
    Inscrit en
    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 : 550
    Points
    550

    Par défaut

    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 ?

  4. #4
    Expert Confirmé Sénior
    Homme Profil pro
    Inscrit en
    mai 2002
    Messages
    3 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : mai 2002
    Messages : 3 037
    Points : 4 613
    Points
    4 613

    Par défaut

    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.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •