IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes PostgreSQL Discussion :

Un UPDATE un peu particulier


Sujet :

Requêtes PostgreSQL

  1. #1
    Futur Membre du Club
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Points : 6
    Points
    6
    Par défaut Un UPDATE un peu particulier
    Bonjour,

    Je fais appel à votre connaissance pour tenter de résoudre une incompréhension:
    Pour la clarté du problème énoncé, je vais rester très théorique car rentrer dans le détail n'apporterai rien et risquerait au contraire de compliquer les choses:

    Soit une table T contenant les colonnes A et B (invariables)
    Soit une fonction F( A, B ) dont la valeur de retour représente une table T'

    Je souhaite stocker le meilleur résultat de la table T' retournée par la fonction F( A, B ) pour chaque ligne de T dans une colonne C

    Pour se faire j'ai essayé plusieurs méthodes telles que :

    - UPDATE T SET C = ( SELECT X FROM F( A, B ) ORDER BY X DESC LIMIT 1 )
    => Error Heading

    - Créer un trigger ON INSERT/UPDATE pour que C = ( SELECT X FROM F( A, B ) ORDER BY X DESC LIMIT 1 )
    - Faire un UPDATE blanc du type UPDATE T SET A = A pour forcer le calcul de C
    => Error Heading

    ...

    Bref je pense que je dois passer à côté de quelque chose qui m'échappe.
    L'erreur de retour ne me permet pas de comprendre l'origine de mon problème, je ne vois pas à quoi cela peut correspondre

    Si quelqu'un pense pouvoir me venir en aide, je lui en serais très reconnaissant

    Cordialement

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Quelle est la déclaration de la fonction F?

  3. #3
    Futur Membre du Club
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Pour la fonction F, je la déclare de la manière suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE OR REPLACE FUNCTION F( A numeric, B numeric ) RETURNS SETOF type_x AS ...
    Ou type_x est un type que j'ai créé avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CREATE TYPE type_x AS (
      X numeric
    );
    Lorsque je fais un:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT X FROM F( a, b )
    (où a et b sont des valeurs test) j'ai bien un tableau de valeurs
    |_X_|
    | 10 |
    | 15 |
    | 12 |

    La fonction F( A, B ) est donc valide (les valeurs qu'elle retourne sont correctes) je souhaite dans cet exemple stocker la valeur 15 dans la colonne C de la ligne de T pour laquelle A = a et B = b

    Merci pour votre aide précieuse

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Le problème est que quand tu fais x est du type numeric et non pas du type type_x.

    Ca doit passer avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    update t set c=(select row(x)::type_x from f(a,b) order by x desc limit 1)

  5. #5
    Futur Membre du Club
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Merci pour votre réponse,

    L'ajout de ::type_x ne change pas le problème malheureusement
    Je souhaite juste apporter une petite correction dans l'énoncé, le message d'erreur n'est pas "Error Header" mais "ERREUR: Invalid heading" précisément (excusez moi pour ce manque de rigueur)

    Ayant fait part de ce problème à un ami, il pense que le problème provient du fait que l'UPDATE attend une valeur sans entête après "C =" et que le fait de retourner une valeur provenant d'un tableau via un SELECT, cette dernière est munie d'une entête que l'UPDATE ne comprend pas, d'où le message d'erreur Invalid Heading (d'après ce que j'en ai compris).

    Sauriez-vous m'en dire un peu plus à ce propos ? Merci encore pour votre aide

    Lorsque je tape "postgresql" + "invalid heading" sur Google, je prend peur par le nombre de résultats

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 732
    Points
    52 732
    Billets dans le blog
    5
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE t SET c=(SELECT MAX(X) AS XMAX FROM f(a,b))
    ???

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  7. #7
    Futur Membre du Club
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE t SET c=(SELECT MAX(X) AS XMAX FROM f(a,b))
    => ERREUR: Invalid heading ( Sans succès, merci pour votre aide )

    Je finis pas me demander si cette forme d'écriture est possible, vous-même avez-vous déjà eu l'occasion d'avoir recours à ce type de procédé pour mettre à jour un champ (invariable par la suite) sur un grand nombre de lignes?

    J'ai bien essayé une procédure plpgsql du type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    FOR r IN SELECT id, A, B FROM T
    LOOP
    X := F( r.A, r.B );
    UPDATE T SET C = X WHERE id = r.id;
    END LOOP;
    mais sans succès non plus...

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    De mémoire je n'ai jamais vu l'erreur "Invalid heading".
    Par ailleurs ça fonctionne pour moi, voici un test avec postgresql 8.4:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    CREATE TYPE type_x AS (x numeric);
     
    CREATE FUNCTION f() returns setof type_x AS $$
    DECLARE
     v type_x;
    BEGIN
     v:=row(1); return next v;
     v:=row(2); return next v;
     return;
    END; $$ language plpgsql;
     
    CREATE TABLE t(a type_x);
     
    INSERT INTO t VALUES (row(10)::type_x);
     
    UPDATE t SET a=(SELECT row(x)::type_x FROM f() ORDER BY x DESC LIMIT 1);
    Il n'y a pas d'erreur et le résultat est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select * from t;
      a  
    -----
     (2)
    (1 row)

  9. #9
    Futur Membre du Club
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Bonsoir estofilo,

    Ma fonction F( A, B ) prend pour paramètres les champs A et B de la table T dans le UPDATE

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    A toi de partir de mon exemple qui passe sans erreur pour le transformer pas à pas en ton cas réel qui provoque l'erreur.

  11. #11
    Futur Membre du Club
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    Merci pour ta réponse, j'ai réadapté un exemple simple pour vérifier que ce procédé ne pose pas de problème avec une fonction qui calcule les solutions à l'équation x^2 = nombre (elle n'a ici aucun intérêt c'est pour l'exemple)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    CREATE TABLE t ( nombre numeric, solution1 numeric, solution2 numeric );
    INSERT INTO t ( nombre, solution1, solution2 ) VALUES ( 4, null, null );
    INSERT INTO t ( nombre, solution1, solution2 ) VALUES ( 9, null, null );
    INSERT INTO t ( nombre, solution1, solution2 ) VALUES ( 16, null, null );
     
    CREATE TYPE type_x AS ( solution numeric );
     
    CREATE FUNCTION f( nombre numeric ) RETURNS SETOF type_x AS $$
      DECLARE
        x type_x;
      BEGIN
        x.solution :=  SQRT( nombre ); RETURN next x;
        x.solution := -SQRT( nombre ); RETURN next x;
        RETURN;
      END;
    $$ LANGUAGE plpgsql;
     
    UPDATE t SET solution1 = ( SELECT solution FROM f( nombre ) ORDER BY solution DESC LIMIT 1 );
    UPDATE t SET solution2 = ( SELECT solution FROM f( nombre ) ORDER BY solution ASC  LIMIT 1 );
    Et cela fonctionne parfaitement.
    Je peux déjà mettre hors de cause la façon d'écrire (un peu particulière?) mon UPDATE.
    Le problème vient de plus haut. Aussi je me pose la question si ma fonction f ne retourne aucune ligne, la colonne C prend elle pour valeur null? (sachant que null est bien autorisé dans la déclaration de ma table T pour la colonne C)

    Je vais continuer à fouiller pas à pas, en te remerciant pour ton aide

  12. #12
    Futur Membre du Club
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Points : 6
    Points
    6
    Par défaut
    J'ai trouvé ma STUPIDE (comme trop souvent malheureusement) erreur :

    Ma fonction F(A,B) n'était pas si parfaite que ça, il y avait des valeurs A et B pour lesquelles elle retournait un message d'erreur que mon UPDATE ne retournait pas à son tour. Merci infiniment à vous deux de m'avoir mis sur la voix (je m'en veux tellement d'être passé à côté d'un truc comme ça).

    En tout cas j'aurais appris beaucoup avec cette erreur à force de chercher les causes possibles

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XSLT]Tableau un peu particulier
    Par JohnBlatt dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 21/06/2006, 18h14
  2. Un tri un peu particulier
    Par GregPeck dans le forum Requêtes
    Réponses: 3
    Dernier message: 08/06/2006, 15h32
  3. Menu un peu particulier avec des onmouseover
    Par Jinroh77 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 21/02/2006, 14h30
  4. #define un peu particulier
    Par greuh dans le forum C
    Réponses: 14
    Dernier message: 12/10/2005, 16h42
  5. Réponses: 2
    Dernier message: 05/01/2004, 11h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo