PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 Re : Général » Condition sur la valeur par défaut d'un champ » 12/08/2013 13:48:40

i20

Nickel! Je ne connaissais pas information_schema!

Par contre comme la colonne "column_default" est un VARCHAR, faut il caster la valeur avant de l'assigner au champ?
Si oui, pas de problème avec les champs dont la valeur par défaut est littérale grâce à la colonne "data_type" mais pour ceux qui utilisent une séquence ou un fonction comment faire?

Ex: champ "created" dont la valeur par défaut est NOW() mais qui est stockée sous la forme 'NOW()' dans information_schema

#2 Re : Général » Condition sur la valeur par défaut d'un champ » 11/08/2013 21:32:51

i20

Désolé pour mon retard ^^


Bon alors voilà, après m'être renseigné un peu sur les triggers, je suis venu à la conclusion que ce qu'il me fallait ressemblait à:

CREATE LANGUAGE plpgsql;

CREATE TABLE users (

    id SERIAL,
    created TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),

    PRIMARY KEY (id)
);

CREATE FUNCTION autofields_function() RETURNS TRIGGER AS
$$
BEGIN
    NEW.id := DEFAULT;
    NEW.created := DEFAULT;
    RETURN NEW;
END;
$$
;

CREATE TRIGGER autofields_trigger 
BEFORE INSERT ON users 
FOR EACH ROW EXECUTE PROCEDURE autofields_function();

Mais voilà, DEFAULT n'existe pas pour plpgsql. Mon problème est exactement le même qu'ici http://www.postgresql.org/message-id/20 … harter.net.
Comment puis-je faire? Y a t'il un moyen de supprimer les valeurs de certains champs du INSERT plutôt que d'essayer de leur assigner DEFAULT?
J'aimerais éviter de devoir aller chercher moi même la valeur par défaut des colonnes tel que suggéré par rjuju si possible.
Et éxécuter un INSERT dans un TRIGGER INSTEAD OF pour pouvoir passer DEFAULT comme valeur va sûrement me donner une merveilleuse boucle infinie, je me trompe?


Merci d'avance pour votre aide

#3 Re : Général » Condition sur la valeur par défaut d'un champ » 08/08/2013 10:46:19

i20

Merci pour ces réponses, je crois que c'est exactement ce qu'il me faut! Oui effectivement je ne sais pas pourquoi je n'avais pas pensé au trigger pour réécrire tout simplement les INSERT au lieu de chercher à tester les valeurs fournies T.T Je vais sûrement tester ça ce soir et ensuite je marquerai le post comme résolu.


Encore merci ^^

#4 Re : Général » Condition sur la valeur par défaut d'un champ » 07/08/2013 18:43:21

i20

Oui c'est vrai pour les UPDATE et peut s'écrire avec une règle toute simple comme :

CREATE RULE rule AS ON UPDATE TO machin
WHERE NEW.created != OLD.created
DO INSTEAD RAISE EXCEPTION 'Cannot update value for field "created"';

Mais mon problème est au moment du INSERT, comment empêcher de fournir une valeur autre que DEFAULT à l'insertion? La règle écrite dans mon précédent post serait bien évaluée avant insertion (comme un trigger before) mais ce qui ne va pas c'est la condition. Je pense qu'en utilisant un trigger je me heurterai au même problème ou alors je me trompe, auriez vous un exemple du trigger que vous proposez?

Merci

#5 Général » Condition sur la valeur par défaut d'un champ » 06/08/2013 17:07:11

i20
Réponses : 9

Bonjour à tous,

Voilà je voudrais savoir, mais je pense que ce que je vais dire peut être considéré comme stupide, s'il était possible dans une clause WHERE de stipuler qu'un champ devait être égal à sa valeur par défaut? Dans mes rêves les plus fous cela donnerait quelque chose comme:

SELECT * FROM machin WHERE champ = DEFAULT;

ou encore

SELECT * FROM machin WHERE champ IS DEFAULT;

Je voudrais savoir si ça peut marcher et si non, y a t'il une autre solution pour arriver à mes fins?

Le but serait d'empêcher l'insertion de valeurs manuelles pour certains champs lors de la création de nouvelles lignes. Par exemple j'ai dans ma table "machin" un champ "created" de type TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() et je voudrais que ce champ ne soit rempli que par sa contrainte DEFAULT et qu'il ne soit pas possible de choisir une autre valeur dans la clause VALUES de INSERT INTO. Là encore dans mon rêve je pourrais écrire:

CREATE RULE rule AS ON INSERT TO machin
WHERE NEW.created IS NOT DEFAULT
DO INSTEAD RAISE EXCEPTION 'Cannot insert custom value for field "created"';

Est-ce possible?

#6 Re : Général » Comportement EXCEPT entre 2 vues » 06/08/2013 16:38:24

i20

Oui, ceci dit pourquoi aller jusqu'à faire une union étant donné qu'on voit bien que rien que sur un except le résultat n'est pas vide?

#7 Re : Général » Comportement EXCEPT entre 2 vues » 04/07/2013 09:17:36

i20

Quelqu'un s'il vous plaît :'( J'aimerais vraiment comprendre! Pour info je suis avec Postgre 8.4 est-ce que ça peut venir de là (ça m'étonnerait) ? ...

#9 Re : Général » Comportement EXCEPT entre 2 vues » 02/07/2013 09:03:35

i20

Merci pour la réponse.

Ceci dit, oui j'ai bien compris que EXCEPT n'était pas commutatif c'est logique, ce que je ne comprend pas c'est comment la 2e comparaison arrive à me renvoyer une ligne qui n'est dans aucune des 2 vues?

#10 Général » Comportement EXCEPT entre 2 vues » 01/07/2013 20:42:54

i20
Réponses : 7

Tout d'abord bonjour à tous vu que c'est mon premier message sur le forum.

Voilà mon problème est le suivant: j'ai 2 vues dont la requête diffère (l'une imbriquée et pas l'autre) mais qui sont sensées renvoyer le même résultat.
Ces vues associent un user_id à un id de package (trial, basic, plus ou privilege), chaque user_id n'ayant qu'une entrée dans la vue. Appelons ces vues
"user_packages1" (sans sous requête) et "user_packages2" (imbriquée).

Voulant vérifier l'égalité de ces 2 vues, je fais un EXCEPT et je m'attend à un résultat vide. Mais il ne l'est pas.
Ma question est: pourquoi le premier EXCEPT renvoie une ligne qui est pourtant bien présente dans "user_packages2". Et également pourquoi le deuxième EXCEPT renvoie une ligne qui n'est dans aucune des 2 vues.



Voici les requêtes de comparaison:
----------------------------------------------------------------------------------------------------------------------------

(SELECT * FROM "user_packages1")
EXCEPT
(SELECT * FROM "user_packages2")

  +--------------------- user_id ------------------+------------------ package_id -----------------+
=|"51d16541-33b8-415d-983e-1b0f256c8bb9"|"51cd6779-852c-4403-b1a7-0308256c8bb9"| (usertest;basic)
  +-------------------------------------------------+--------------------------------------------------+


(SELECT * FROM "user_packages2")
EXCEPT
(SELECT * FROM "user_packages1")

  +--------------------- user_id ------------------+------------------ package_id ----------------+
=|"51d16541-33b8-415d-983e-1b0f256c8bb9"|"51cd6779-15b8-47d0-8f64-0308256c8bb9"| (usertest;trial)
  +-------------------------------------------------+-------------------------------------------------+




Sachant que l'entrée pour cet user particulier est la même dans les 2 vues:
----------------------------------------------------------------------------------------------------------------------------

(SELECT * FROM "user_packages1" WHERE user_id = '51d16541-33b8-415d-983e-1b0f256c8bb9')

  +--------------------- user_id ------------------+------------------ package_id -----------------+
=|"51d16541-33b8-415d-983e-1b0f256c8bb9"|"51cd6779-852c-4403-b1a7-0308256c8bb9"| (usertest;basic)
  +-------------------------------------------------+-------------------------------------------------+


(SELECT * FROM "user_packages2" WHERE user_id = '51d16541-33b8-415d-983e-1b0f256c8bb9')

  +--------------------- user_id ------------------+------------------ package_id -----------------+
=|"51d16541-33b8-415d-983e-1b0f256c8bb9"|"51cd6779-852c-4403-b1a7-0308256c8bb9"| (usertest;basic)
  +-------------------------------------------------+-------------------------------------------------+




Voici le code des 2 vues (elles ont exactement le même nombre de lignes):
----------------------------------------------------------------------------------------------------------------------------

CREATE VIEW "user_packages1" AS 
SELECT
    DISTINCT ON (UI.user_id) user_id, 
    P.id AS package_id 
FROM
    "user_items" AS UI,
    "packages" AS P,
    "package_types" AS PT
WHERE
    UI.model = 'Package' AND
    UI.model_foreign_key = P.id AND
    P.package_type_id = PT.id
ORDER BY
    UI.user_id,
    PT.weight DESC;

----------------------------------------------------------------------------------------------------------------------------

CREATE VIEW "user_packages2" AS 
SELECT DISTINCT ON (UAP.user_id) user_id, UAP.model_foreign_key AS package_id 
FROM (
  SELECT UI.user_id, UI.model_foreign_key, PT.name
  FROM "user_items" UI
  INNER JOIN "packages" P
  ON P.id=UI.model_foreign_key
  INNER JOIN "package_types" PT
  ON PT.id=P.package_type_id
  WHERE UI.model='Package'
  ORDER BY PT.weight DESC
) AS UAP;

----------------------------------------------------------------------------------------------------------------------------


Ce que je ne comprend pas c'est d'où peux sortir la ligne renvoyée par le second EXCEPT étant donné qu'elle n'est présente dans aucune des deux vues?!


Après m'être cassé la tête pendant un "petit" moment, j'en suis venu à la conclusion que EXCEPT ne devait pas traiter les requêtes séparément avant d'exclure mais plutôt tenter une optimisation (qui aurait foiré ici?) car sinon il n'y a aucune chance que le résultat de la seconde comparaison soit ce qu'il est.

A savoir, ces vues récupèrent pour chaque user le meilleur package qui lui est attaché, plus explicitement dans la table sur laquelle les vues sont calculées le user "usertest" ('51d16541-33b8-415d-983e-1b0f256c8bb9') a 2 entrées, une avec le package "trial" ('51cd6779-15b8-47d0-8f64-0308256c8bb9'), l'autre avec le package "basic" ('51cd6779-852c-4403-b1a7-0308256c8bb9') soit:

+--------------------- user_id ------------------+------------------ package_id -----------------+
|                              ...                              |                             ...                              |
|"51d16541-33b8-415d-983e-1b0f256c8bb9"|"51cd6779-852c-4403-b1a7-0308256c8bb9"| (usertest;basic)
|"51d16541-33b8-415d-983e-1b0f256c8bb9"|"51cd6779-15b8-47d0-8f64-0308256c8bb9"| (usertest;trial)
|                              ...                              |                             ...                              |
+-------------------------------------------------+-------------------------------------------------+

Il n'y a donc que de là que pourrait venir le résultat de la seconde comparaison à priori ... Est-ce un bug ou ai-je simplement mal fait quelque chose? Je vous remercie par avance pour toute aide que vous pourrez m'apporter car là j'abandonne ^^

Pied de page des forums

Propulsé par FluxBB