Vous n'êtes pas identifié(e).
Bonjour à tous.
Je me suis basé sur l'exemple donné dans la doc (postgreSQL 9.1.4) pour créer une table partitionnée avec un trigger. La table est partitionnée sur l'année, la fonction appelée par le trigger crée la table partitionnée si elle n'existe pas et insère l'occurrence dans celle-ci.
Le problème est dans l'instruction : EXECUTE 'INSERT INTO ' || v_table || ' VALUES (' NEW.* ')';
Le NEW.* ne renvoie pas les chaînes de caractères entourées de quotes, ce qui fait planter l'INSERT.
Auriez-vous une solution ? Merci d'avance.
Voici le code :
CREATE OR REPLACE FUNCTION cvae_insert_trigger() RETURNS TRIGGER AS $$
DECLARE
v_nombre SMALLINT;
v_annee SMALLINT;
v_table VARCHAR;
BEGIN
v_annee := NEW.annee;
v_table := 'cvae' || v_annee;
SELECT count(*) INTO v_nombre FROM pg_tables WHERE pg_tables.tablename = v_table;
IF ( v_nombre = 0 ) THEN
-- Creation de la partition si elle n'existe pas
EXECUTE 'CREATE TABLE ' || v_table || '( '
|| 'PRIMARY KEY (annee, idcvae), '
|| 'CONSTRAINT ' || v_table || '_annee_check CHECK (annee = ' || v_annee || '), '
|| 'CONSTRAINT ' || v_table || '_commune_fkey FOREIGN KEY (codecommunedpt) REFERENCES commune(codecommunedpt), '
|| 'CONSTRAINT ' || v_table || '_sousclasse_fkey FOREIGN KEY (codesousclasse) REFERENCES naf_sous_classe(codesousclasse), '
|| 'CONSTRAINT ' || v_table || '_voie_fkey FOREIGN KEY (codevoie, codecommunedpt) REFERENCES voie(codevoie, codecommunedpt), '
|| 'CONSTRAINT ' || v_table || '_formejuridique_fkey FOREIGN KEY (idformejuridique) REFERENCES forme_juridique(idformejuridique), '
|| 'CONSTRAINT ' || v_table || '_zone_fkey FOREIGN KEY (idzonage, idzone) REFERENCES zone(idzonage, idzone), '
|| 'CONSTRAINT ' || v_table || '_entreprise_fk FOREIGN KEY (siren) REFERENCES entreprise(siren), '
|| 'CONSTRAINT ' || v_table || '_etablissement_fkey FOREIGN KEY (siren, nic) REFERENCES etablissement(siren, nic)) '
|| 'INHERITS (cvae)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_commune ON ' || v_table || ' (CodeCommuneDpt)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_voie ON ' || v_table || ' (CodeVoie, CodeCommuneDpt)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_formejuridique ON ' || v_table || ' (IdFormeJuridique)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_entreprise ON ' || v_table || ' (SIREN)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_etablissement ON ' || v_table || ' (SIREN, NIC)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_nafsousclasse ON ' || v_table || ' (CodeSousClasse)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_zone ON ' || v_table || ' (IdZonage, IdZone)';
EXECUTE 'CREATE INDEX i_' || v_table || '_denomination ON ' || v_table || ' (Denomination)';
END IF;
EXECUTE 'INSERT INTO ' || v_table || ' VALUES (' NEW.* ')';
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER cvae_insert_trigger
BEFORE INSERT ON cvae
FOR EACH ROW EXECUTE PROCEDURE cvae_insert_trigger();
Voici l'erreur :
ERROR: syntax error at or near ","
LINE 1: INSERT INTO cvae2012 VALUES ((2012,1,123456789,,,,toto,,,,...
^
QUERY: INSERT INTO cvae2012 VALUES ((2012,1,123456789,,,,toto,,,,,,,,,,,,,,,,,,,,,,))
CONTEXT: PL/pgSQL function "cvae_insert_trigger" line 35 at EXECUTE statement
Hors ligne
Le code que vous indiquez n'est pas correct syntaxiquement sur cette ligne :
EXECUTE 'INSERT INTO ' || v_table || ' VALUES (' NEW.* ')';
J'obtiens ceci :
ERROR: syntax error at or near "."
LINE ... : EXECUTE 'INSERT INTO ' || v_table || ' VALUES (' NEW.* ')';
Donc difficile de dire d'où vient votre problème réel.
Concernant l'exemple de la documentation, il fonctionne. La seule différence entre ce code et le votre est que vous utilisez EXECUTE.
Guillaume.
Hors ligne
Merci pour la réponse rapide.
J'ai changé la syntaxe dans la ligne suivante (j'ai enlevé les parenthèses) mais j'ai toujours le problème :
EXECUTE 'INSERT INTO ' || v_table || ' VALUES ' || NEW.*;
ERROR: syntax error at or near ","
LINE 1: INSERT INTO cvae2012 VALUES (2012,1,123456789,,,,toto,,,,,...
^
QUERY: INSERT INTO cvae2012 VALUES (2012,1,123456789,,,,toto,,,,,,,,,,,,,,,,,,,,,,)
CONTEXT: PL/pgSQL function "cvae_insert_trigger" line 35 at EXECUTE statement
Après la valeur numérique 123456789, je suppose qu'il devrait y avoir ,'' (idem pour la valeur toto qui devrait être 'toto').
Hors ligne
Vous arrivez à enregistrer la fonction ? parce que, moi, j'ai l'erreur de syntaxe lors du 'CREATE OR REPLACE', pas lors de 'lexécution.
Guillaume.
Hors ligne
oui, la création de la fonction s'exécute bien avec ce code :
CREATE OR REPLACE FUNCTION cvae_insert_trigger() RETURNS TRIGGER AS $$
DECLARE
v_nombre SMALLINT;
v_annee SMALLINT;
v_table VARCHAR;
BEGIN
v_annee := NEW.annee;
v_table := 'cvae' || v_annee;
SELECT count(*) INTO v_nombre FROM pg_tables WHERE pg_tables.tablename = v_table;
IF ( v_nombre = 0 ) THEN
-- Creation de la partition si elle n'existe pas
EXECUTE 'CREATE TABLE ' || v_table || '( '
|| 'PRIMARY KEY (annee, idcvae), '
|| 'CONSTRAINT ' || v_table || '_annee_check CHECK (annee = ' || v_annee || '), '
|| 'CONSTRAINT ' || v_table || '_commune_fkey FOREIGN KEY (codecommunedpt) REFERENCES commune(codecommunedpt), '
|| 'CONSTRAINT ' || v_table || '_sousclasse_fkey FOREIGN KEY (codesousclasse) REFERENCES naf_sous_classe(codesousclasse), '
|| 'CONSTRAINT ' || v_table || '_voie_fkey FOREIGN KEY (codevoie, codecommunedpt) REFERENCES voie(codevoie, codecommunedpt), '
|| 'CONSTRAINT ' || v_table || '_formejuridique_fkey FOREIGN KEY (idformejuridique) REFERENCES forme_juridique(idformejuridique), '
|| 'CONSTRAINT ' || v_table || '_zone_fkey FOREIGN KEY (idzonage, idzone) REFERENCES zone(idzonage, idzone), '
|| 'CONSTRAINT ' || v_table || '_entreprise_fk FOREIGN KEY (siren) REFERENCES entreprise(siren), '
|| 'CONSTRAINT ' || v_table || '_etablissement_fkey FOREIGN KEY (siren, nic) REFERENCES etablissement(siren, nic)) '
|| 'INHERITS (cvae)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_commune ON ' || v_table || ' (CodeCommuneDpt)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_voie ON ' || v_table || ' (CodeVoie, CodeCommuneDpt)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_formejuridique ON ' || v_table || ' (IdFormeJuridique)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_entreprise ON ' || v_table || ' (SIREN)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_etablissement ON ' || v_table || ' (SIREN, NIC)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_nafsousclasse ON ' || v_table || ' (CodeSousClasse)';
EXECUTE 'CREATE INDEX ifk_' || v_table || '_zone ON ' || v_table || ' (IdZonage, IdZone)';
EXECUTE 'CREATE INDEX i_' || v_table || '_denomination ON ' || v_table || ' (Denomination)';
END IF;
EXECUTE 'INSERT INTO ' || v_table || ' VALUES ' || NEW.*;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Hors ligne
OK. Là, vous demandez en fait de transformer la ligne (NEW.*) en chaîne de caractères (opérateur || pour la concaténation). Ce que fait PostgreSQL, sans mettre de guillemets, ni sans faire d'échappements. Vous ne pourrez pas aller contre ce comportement. NEW.* n'est pas utilisable dans votre cas.
Guillaume.
Hors ligne
Il n'y a pas moyen de contourner ce comportement pour que le NEW soit interprété comme une commande et que son résultat ne soit pas traduit en chaîne de caractères ?
Hors ligne
Non.
Guillaume.
Hors ligne
Tant pis, j'aurai tenté.
Merci pour les réponses.
Arnaud.
Hors ligne