Vous n'êtes pas identifié(e).
Pages : 1
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?
Hors ligne
Bonsoir,
Vous pouvez envisager l'écriture d'un trigger *before* qui vérifie que vous ne ne modifiez pas la valeur du champ interdit. Si tel était le cas, vous sortez en erreur de la fonction appelée par le trigger.
Stéphane Schildknecht
Conseil, formations et support PostgreSQL
http://www.loxodata.com
Hors ligne
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
Hors ligne
Vous pourriez envisager un trigger qui ne prenne pas en compte les champs interdits.
Ou plus simplement ne pas inclure les champs dans la commande d'insert/update.
Vous pouvez aussi créer une table d'historisation sous la forme
Table_origine|type_mod|date_heure
Machin | I | default now()
Machin | U | default now()
Avec des triggers sur les tables qui déclenchent les insertions dans la table d'historisation.
Stéphane Schildknecht
Conseil, formations et support PostgreSQL
http://www.loxodata.com
Hors ligne
Vous pouvez utiliser la requête suivante pour trouver la valeur par défaut d'une colonne (le type retourné est text):
SELECT d.adsrc
FROM pg_class c
JOIN pg_namespace n ON c.relnamespace = n.oid
JOIN pg_attribute a ON a.attrelid = c.oid
JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = a.attnum
WHERE n.nspname = 'nom_schema' AND c.relname = 'nom_table' AND a.attname = 'nom_colonne';
Julien.
https://rjuju.github.io/
Hors ligne
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 ^^
Hors ligne
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
Dernière modification par i20 (11/08/2013 23:59:46)
Hors ligne
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;
...
Est-ce possible?
Vos rêves ne sont pas fous, mais c'est un petit peu plus compliqués :
La vue de métadonnées INFORMATION_SCHEMA.COLUMNS contient la valeur par défaut de toute colonne de toute table. Dès lors vous pouvez faire :
SELECT * FROM machin WHERE champ =
(SELECT COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'public'
AND TABLE_NAME = 'machin'
AND COLUMN_NAME = 'champ');
A +
Dernière modification par SQLpro (12/08/2013 10:48:27)
Frédéric Brouard, alias SQLpro, ARCHITECTE DE DONNÉES, Expert langage SQL
Le site sur les SGBD relationnel et langage SQL : http://sqlpro.developpez.com/
Modélisation de données, conseil, expertise, audit, optimisation, tuning, formation
* * * * * Enseignant CNAM PACA, ISEN Toulon, CESI Aix en Provence * * * * *
Hors ligne
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
Dernière modification par i20 (12/08/2013 13:49:05)
Hors ligne
Oui, à caster explicitement.
Guillaume.
Hors ligne
Pages : 1