Vous n'êtes pas identifié(e).
Merci du retour,
Je poursuis mes investigations.
A présent, je cherche à écrire une fonction dont le rôle sera la suppression d'une table passée en paramètre, puis de de la créer
J'utilise pour celà du SQL dynamique qui semble incontournable. Je butte dans l'écriture de la chaine contenant la requête de suppression de la table. Il semble également nécessaire d'utiliser un bloc 'DO' pour exécuter le code : IF EXISTS. Est ce vraiment nécessaire ?
Ci-dessous, l'exemple de code que je tente d'écrire :
CREATE OR REPLACE FUNCTION test_svga (TAB_NAME VARCHAR, REF VARCHAR)
RETURNS INTEGER
AS
$$
DECLARE
C_Ret INTEGER;
Str_Sql VARCHAR (5000); -- Chaine requete SQL.
BEGIN
C_Ret := 0;
-- La table a supprimer se nomme : TAB_NAME_REF.
/*
Str_Sql := 'DO$$ ' || 'BEGIN ';
*/
/*
Str_Sql := Str_Sql || 'IF EXISTS (SELECT tablename FROM pg_tables WHERE (tablename = ''' || LOWER (TAB_NAME) || '''_''' || REF || '''))' || ' THEN DROP TABLE ' || LOWER (TAB_NAME) || '''_''' || REF || '''') || ' CASCADE; END IF; ';
*/
Str_Sql := Str_Sql || 'IF EXISTS (SELECT tablename FROM pg_tables WHERE (tablename = ''' || LOWER (TAB_NAME) || '_' || REF || ''')' || ' THEN RAISE NOTICE ''ceci est un test''; END IF; ';
Str_Sql := Str_Sql || 'END; \$\$';
RAISE NOTICE 'Str_SQL : (%)', Str_Sql;
EXECUTE Str_Sql;
RETURN C_Ret;
END;
$$ LANGUAGE plpgsql;
SELECT test_svga ('MATABLE', '00000010');
J'ai une erreur de syntaxe au niveau du DO ou $$, et je ne vois pas encore comment bien l'écrire.
ERREUR: erreur de syntaxe sur ou près de « ' || ' »
LINE 15: Str_Sql := 'DO$$ ' || 'BEGIN ';
^
********** Erreur **********
ERREUR: erreur de syntaxe sur ou près de « ' || ' »
État SQL :42601
Caractère : 307
Un exemple de code sera apprécié.
D'avance merci.
Bonjour,
Je cherche à créer une ou plusieurs tables dans un traitement SQL.
Je pense qu'il faut passer par du SQL dynamyque, mais ceci reste à confirmer.
J'ai fait quelques essais, qui ne donnent pas à ce jour de bons résultats.
Ci-dessous, le code utilisé :
DO
$$
DECLARE
Str_Sql VARCHAR (5000);
BEGIN
Str_Sql := 'SELECT * INTO MATABLEB FROM MATABLEA;';
EXECUTE Str_Sql;
END;
$$
Ceci ne semble pas possible dans un bloc de code plpgsql. (Le code génère des erreurs. Lacommande EXECUTE ne serait pas autorisée.)
Quelle serait la meilleure méthode pour réaliser ceci dans un bloc de code plpgsql ?
(Un exemple de code serait très appréciable)
D'avance merci de votre retour.
Cordialement.
Merci de l'information.
Comment alors le réaliser ?
Auriez-vous un exemple à me proposer ?
Ce que je cherche à obtenir est avoir l'assurance que les 3 INSERTS soient réellement effectués avant la ligne en erreur.
Pourrait t'on forcer l'exécution d'un bloc de code EXCEPTION dans lequel seraient enregistrées les 3 lignes d'INSERT ? (RAISE ?)
Merci pour vos propositions.
Merci de la réponse.
L'instruction SAVEPOINT me parait effectivement adaptée pour mon exemple.
Je l'ai mis en oeuvre, mais je constate que cette instruction n'est pas autorisée dans le langage PL/pgsql.
Si une procédure stockée est considérée comme une opération atomique, peux t'on imaginer que dans mon exemple, les INSERT seraient réalisés par l'appel à une procédure stockée, on obtiendrait le résultat attendu ?
Je vais faire l'essai dans ce sens.
D'avance merci de votre retour.
Bonjour,
Je m'interroge sur un problème que je rencontre dans l'écriture d'une fonction.
Dans la documentation de PostgreSQL,Il est dit que PostgreSQL fonctionne en autoCommit.
Je comprends par là qu'à chaque action sur un enregistrement (INSERT, DELETE, UPDATE), cette action est enregistrée dans la table.
Or dans mon exemple de fonction ci-dessous, je constate que, si une instruction provoque une erreur, les actions réalisées précédemment (3 INSERT) ne sont pas enregistrées dans la table, comme si un ROLLBACK aurait été fait (annulant les actions précédentes).
Dans l'exemple de la fonction, 3 actions INSERT sont réalisées, puis suit une action provoquant une erreur.
Dans un bloc EXCEPTION interceptant l'erreur, 2 actions INSERT différentes sont réalisées.
Quand je regarde le résultat obtenu dans la table, je constate uniquement les 2 actions INSERT effectuées dans le bloc Exception.
Les actions INSERT précédentes n'apparaissent pas, comme si le COMMIT ne se faisait pas ou aurait été annulé par un ROLLBACK.
Quelqu'un peut t'il éclairer ma lanterne sur ce qui se passe réellement ?
Peut t'on obtenir le résultat que je souhaite, et quel serait la méthode ?
D'avance merci de votre retour.
CREATE OR REPLACE FUNCTION MyFunction (PAR_1 varchar,
PAR_2 varchar) RETURNS INTEGER
AS
$$
DECLARE
C_Ret INTEGER; -- Code retour de fonction.
BEGIN
C_Ret := 0;
INSERT INTO TAB1 (FIELD1, FIELD2)
VALUES ('VAL11', 'VAL21');
INSERT INTO TAB1 (FIELD1, FIELD2)
VALUES ('VAL12', 'VAL22');
INSERT INTO TAB1 (FIELD1, FIELD2)
VALUES ('VAL13', 'VAL23');
Instruction SQL provoquant une erreur.
RETURN C_Ret;
EXCEPTION
WHEN OTHERS THEN
BEGIN
INSERT INTO TAB1 (FIELD1, FIELD2)
VALUES ('VAL14', 'VAL24');
INSERT INTO TAB1 (FIELD1, FIELD2)
VALUES ('VAL15', 'VAL25');
C_Ret := 2;
RETURN C_Ret;
END;
END;
$$ LANGUAGE plpgsql;
Merci de la réponse
Bonjour,
Je bute sur un problème simple se résumant à une opération d'addition d'un nombre de jour sur une date.
Ci-dessous, un extrait du code afin d'illustrer le problème rencontré.
Nbr_Jour INTEGER; -- Variable de nombre de jours.
Date_Def TIMESTAMP; -- Date debut par defaut.
Nbr_Jour := TO_NUMBER (TO_CHAR (NOW(), 'ID'), '99') - 1;
-- Resultat aujourd'hui 21/12/2016 : 2.
Date_Def := Now ();
--Date_Def := Date_Def - integer '1';
--Date_Def := Date_Def - integer TO_CHAR (Nbr_Jour, '99');
Date_Def := Date_Def - Nbr_Jour;
Ci-dessous, le message d'erreur obtenu
En commentaire, dans l'exemple du code, les essais déjà réalisés, générant le même code erreur.
Erreur PostgreSQL : 42883 Message : l'opérateur n'existe pas : timestamp without time zone - integer
Comment, simplement, résoudre ce problème simple (de base) ?
D'avance merci de votre retour.
Comment récupérer l'oid d'une fonction ?
Celui-ci n'est pas présent dans la table pg_proc.
Merci de l'information.
Comment implémenter le code pour fabriquer la chaine de caractères correspondant au type de chacun des paramètres de la fonction ?
Dans mon exemple, une fonction a une liste de paramètres :
SELECT p.proargtypes
FROM pg_proc p
where (p.proname = 'Ma_fonction')
"1043 1043 25 25 25 1114 1043 1043 1043 23 1043 23"
select typname, typelem from pg_type
where (typelem in (1043, 23, 25, 1114));
"_int4";23
"_text";25
"_varchar";1043
"_timestamp";1114
Quand j'observe les types de paramètres liés à mon exemple de fonction, j'obtiens des valeurs différentes de celles obtenues dans la table pg_type pour les valeurs rencontrées.
IN namefile character varying,
IN buff_err character varying,
IN buff_pg1 text,
IN buff_pg2 text,
IN buff_pg3 text,
IN dat_trt timestamp without time zone,
IN mod_trt character varying,
IN num_j character varying,
IN nam_l character varying,
INOUT nb_l integer,
IN nam_i character varying,
INOUT nb_i integer)
Aussi, quelles sont les valeurs de types de paramètres à utiliser pour identifier la fonction ?
Un exemple de code pour l'obtenir ?
D'avance merci de votre réponse.
Il manque le DO en début du bloc de code fourni en exemple.
Après quelques recherches complémentaires, l'erreur produite viendrait de l'absence des paramètres fournis entre parenthèses de la fonction.
D'une manière générale, quelle serait le code pour fournir la chaine de caractères correspondant aux paramètres de la fonction ?
D'avance merci de votre retour.
Bonjour,
Ci-dessous, une erreur d'exécution obtenue lors de l'invocation de la fonction : EXECUTE, dont je ne vois pas la cause :
$$
DECLARE
r record;
user_name VARCHAR (255);
schema_name VARCHAR (255);
BEGIN
user_name := 'decatn';
schema_name := 's_etptabe';
FOR r IN SELECT p.proname, p.proowner, p.pronamespace
FROM pg_proc p
WHERE (p.proowner = (select u.usesysid
from pg_user u
where (u.usename = user_name)))
AND (p.proowner = (select nspowner
From pg_namespace
Where (nspname = schema_name)))
LOOP
EXECUTE 'ALTER FUNCTION ' || quote_ident(schema_name) || '.' || quote_ident(r.proname) || ' SET SCHEMA public;';
END LOOP;
END;
$$
Message obtenu :
ERREUR: erreur de syntaxe sur ou près de « SET »
LINE 1: ALTER FUNCTION s_etptabe.inst_wepal SET SCHEMA public;
^
QUERY: ALTER FUNCTION s_etptabe.inst_wepal SET SCHEMA public;
CONTEXT: fonction PL/pgsql inline_code_block, ligne 19 à instruction EXECUTE
********** Erreur **********
ERREUR: erreur de syntaxe sur ou près de « SET »
État SQL :42601
Contexte : fonction PL/pgsql inline_code_block, ligne 19 à instruction EXECUTE
Le message est peu explicite.
Avez-vous une idée de la cause de l'erreur ?
D'avance merci, de votre retour.
Merci de la réponse.
Comment contacter EnterpriseDB ?
Avez-vous des liens ou bien des forums ?
Merci du retour,
Si la restauration d'un schéma vers un autre n'est pas possible simplement, l'idée serait de définir ce schéma restauré comme le schéma par défaut de l'utilisateur, ceci afin de ne pas devoir préciser systématiquement le nom du schéma dans le préfixe des objets de type table ou autre.
Comment le réaliser simplement pour une exécution à partir de psql ?
Merci du retour,
J'avais réalisé, depuis mon dernier message, un essai en utilisant l'option -d<nom de base>, mais la restauration s'effectue malgré tout dans le schéma d'origine.
Aussi, j'ai imaginé une possibilité de générer le dump sans les informations de schéma.
J'ai ajouté l'option -O dans la commande de pg_dump comme ci-dessous :
pg_dump -h ${PGSERVEUR} -U ${PGUSR} -p ${PGPORT} -Ft -O -f Data_sgbd.dmp ${PGDB}
Là encore, la restauration s'effectue dans le schéma d'origine.
pg_restore -Uspie -dSPIE -c -O -Ft -v -w Data_sgbd.dmp >ml.log
Aussi, quelle est la bonne pratique pour restaurer un dump appartenant à un schéma d'origine, vers un schéma différent ?
Un autre point que j'ai essayé d'approfondir est la possibilité d'associer un schéma par défaut à un utilisateur.
Est-ce possible ?
Il semble que le schéma public soit toujours le schéma par défaut.
Pouvez-vous le confirmer ?
D'avance merci de votre retour.
Merci du retour,
La commande s'exécute à présent, je constate sur la console de lancement, un défilement du déroulement du script.
Mais le résultat obtenu n'est pas celui attendu, car la table à recharger reste vide, je l'avais vidée dans les 2 bases avant de lancer la commande pour m'assurer du chargement à partir du dump.
Dans l'exemple, la table à recharger se nomme : plpacti.
Ci-dessous, la commande lancée :
pg_restore -Uspie -O -t plpacti -Ft -w test_tab.dmp >trt.log
Rappel du but à atteindre :
.Recharger une ou plusieurs tables à partir d'un fichier dump issu d'une base de données se nommant : test, dans une base de données différente se nommant : spie.
J'ai utilisé l'option -O afin de ne pas reprendre les informations du owner initial, en espérant que le owner retenu soit celui issu de la connexion.
Ci-dessous, un extrait du fichier trt.log :
--
-- PostgreSQL database dump
--
SET statement_timeout = 0;
SET lock_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = true;
--
-- Name: plpacti; Type: TABLE; Schema: public; Owner: -; Tablespace:
--
CREATE TABLE plpacti (
matri character varying(10) NOT NULL,
dat timestamp(3) without time zone NOT NULL,
hdeb character varying(4) NOT NULL,
hfin character varying(4),
codelieu character varying(10),
codequal character varying(10),
jour smallint,
novac smallint,
fixe character varying(1),
valide character varying(1),
prispost integer,
finpost integer,
duraff integer,
flgmot character varying(1)
);
--
-- Data for Name: plpacti; Type: TABLE DATA; Schema: public; Owner: -
--
COPY plpacti (matri, dat, hdeb, hfin, codelieu, codequal, jour, novac, fixe, valide, prispost, finpost, duraff, flgmot) FROM stdin;
1700935 2016-06-06 00:00:00 0900 1200 00006621 V 1 1 0 0 0 180 0
0300209 2016-05-13 00:00:00 1148 1500 00016101 V 5 1 0 0 0 192 0
000001 2016-01-18 00:00:00 0800 1200 00006616 V 1 1 0 0 0 240 0
000001 2016-01-18 00:00:00 1400 1800 00006616 V 1 2 0 0 0 240 0
000001 2016-01-19 00:00:00 0800 1200 00006616 V 2 1 0 0 0 240 0
\.
--
-- PostgreSQL database dump complete
--
Quel peut être l'origine de mon problème ?
D'avance merci de votre retour.
Je tente désespéremment à restaurer un ensemble des tables issues d'une autre base de données, à partir d'un fichier dump que j'ai généré à partir de la commande pg_dump exécuté sur l'autre base de données.
commande exécutée pour la génération du dump :
pg_dump -U test -t table1 -t table2 -t table3 -t table4 -t table5 -t table6 -t table7 -t table8 -Fct -w -f test_tab.dmp
Commande exécutée pour la restauration du dump :
pg_restore -Uuser2 -Ft -w -f test_tab.dmp
La commande est exécutée dans une fenêtre de console (plate forme windows, postgreSQL 9.4), mais ne se termine jamais.
Aucune activité des processeurs, un kill de la commande est nécessaire pour mettre fin à celle-ci.
Aucune trace dans le fichier log de postgreSQL du répertoire pg_log.
Que faire pour mieux diagnostiquer le problème et le résoudre ?
D'avance merci de votre retour.
J'utilise le deboggeur interne à PgAdminIII pour la mise au point.
Lors de sessions de déboggage, lorsque je fais du pas à pas (F11) pour suivre le déroulement du deboggage, il arrive fréquemment que j'ai le message : (step into) en attente de réponse du client.
Lorsque ce message apparaît, je suis bloqué, et le seul moyen de reprendre la main est de killer le programme PgAdminIII. Une fois cette action faite, un des process du serveur Postgres occupe presque les 100% de la cpu du serveur. L'arrêt du SGBD par le gestionnaire de service est inopérant. Le seul moyen de s'en sortir est de killer tous les prcess Postgres, puis de relancer le SGBD également depuis le gestionnaire de services. Une nouvelle session peut être à nouveau ouverte.
Ce phénomène n'est pas systématique (aléatoire).
Avez-vous une explication à ce phénomène ? Comment peut t'on y remédier ?
Merci de la réponse.
En modifiant la requête comme ci-dessous, on contourne le problème de l'usage du WITH :
SELECT * FROM (
SELECT DISTINCT groupe,libelle FROM sfpgrps WHERE groupe NOT IN (SELECT DISTINCT grouph FROM hopempl)
INTERSECT
SELECT DISTINCT hierar,libelle FROM sfphierg WHERE hierar NOT IN (SELECT DISTINCT hierar FROM sfphierd
UNION
SELECT DISTINCT hierar FROM sfpsupl)
) as req1;
Quel serait le bon usage du WITH ?
Désolé,
Je n'ai fourni la bonne requête posant problème.
La voici ci-dessous :
CREATE TABLE temp_res AS
SELECT * FROM (WITH req1 as (SELECT DISTINCT hierar FROM sfphierd
UNION
SELECT DISTINCT hierar FROM sfpsupl)
SELECT DISTINCT groupe,libelle FROM sfpgrps WHERE groupe NOT IN (SELECT DISTINCT grouph FROM hopempl)
INTERSECT
SELECT DISTINCT hierar,libelle FROM sfphierg WHERE hierar NOT IN (SELECT * FROM req1)
);
Bonjour,
Je transpose sous PostgreSQL quelques requêtes écrites initialement sous Oracle.
J'ai la requête ci-dessous qui me pose problème.
CREATE TABLE temp_res AS
SELECT hierar FROM (WITH req1 as (SELECT DISTINCT hierar FROM sfphierd
UNION
SELECT DISTINCT hierar FROM sfpsupl)
SELECT DISTINCT groupe,libelle FROM sfpgrps WHERE groupe NOT IN (SELECT DISTINCT grouph FROM hopempl)
INTERSECT
SELECT DISTINCT hierar,libelle FROM sfphierg WHERE hierar NOT IN (SELECT * FROM req1)
);
J'ai le message suivant lorsque je l'exécute :
la sous-requête du FROM doit avoir un alias
Avez vous une idée sur la nature de l'erreur, et comment la transposer ?
D'avance merci de vos retours.
Bonjour,
Je cherche à importer des données dans une table à partir de fichier de type CSV.
Pour cela j'utilise le client psql en ligne de commande
Cette commande fonctionne :
psql -d test -U test -c "COPY matable FROM STDIN WITH (FORMAT csv, DELIMITER ';');" <fichier.txt
Cette commande ne fonctionne pas :
psql -d test -U test -c "COPY matable FROM STDIN WITH (FORMAT csv, DELIMITER ';', QUOTE '"');" <fichier.txt
Je voulais préciser le caractère d'encadrement des chaines de caractères en rajoutant l'option QUOTE.
La commande me parait conforme selon la syntaxe décrite dans la documentation.
COPY nom_table [ ( nom_colonne [, ...] ) ]
FROM { 'nom_fichier' | PROGRAM 'commande' | STDIN }
[ [ WITH ] ( option [, ...] ) ]
COPY { nom_table [ ( nom_colonne [, ...] ) ] | ( requête ) }
TO { 'nom_fichier' | PROGRAM 'commande' | STDOUT }
[ [ WITH ] ( option [, ...] ) ]
où option fait partie
de :
FORMAT nom_format
OIDS [ oids ]
FREEZE [ booléen ]
DELIMITER 'caractère_délimiteur'
NULL 'chaîne_null'
HEADER [ booléen ]
QUOTE 'caractère_guillemet'
ESCAPE 'caractère_échappement'
FORCE_QUOTE { ( nom_colonne [, ...] ) | * }
FORCE_NOT_NULL ( nom_colonne [, ...] )
FORCE_NULL ( nom_colonne [, ...] )
ENCODING 'nom_encodage'
Où est l'erreur ?
D'autre part, je souhaitai initialement préciser l'origine du fichier par la clause FROM { 'nom_fichier', plutôt que STDIN, mais le fichier semblait introuvable (message d'erreur).
Dans ce cas d'utilisation, où est attendu le fichier ?, côté serveur ou côté client ?
Si côté serveur, et que le chemin n'est pas précisé, je suppose qu'il y a un emplacement par défaut. Quel est t'il dans ce cas ?
D'avance merci de vos retours.
Merci du retour.
Cela semble correspondre à ma demande.
Je vais exploiter de ce pas cette piste.
Bonjour,
Je cherche à retourner les codes d'erreurs, ainsi que les messages correspondant dans le cas où ces erreurs se produiraient, afin de les restituer à l'utilisateur de façon explicite.
Sous Oracle j'avais implémenté une procédure qui répondait à ce besoin.
Ci-dessous, le code correspondant :
FUNCTION Repertorie_Erreurs (Buff_Err VARCHAR2) RETURN NUMBER
IS
-- Déclarations
Ret NUMBER; -- Code de retour
Err_Num NUMBER; -- Erreur Oracle
Err_Msg VARCHAR2 (100); -- Message erreur Oracle
Buf_Msg VARCHAR2(1000); -- Buffer de message.
BEGIN
Ret := 0;
Err_Num := SQLCODE;
Err_Msg := SUBSTR(SQLERRM, 1, 100);
...
Ret := 1;
RETURN Ret;
END;
La variable SQLCODE permettait de récupérer le code de l'erreur.
La variable SQLERRM permettait de récupérer le texte du message.
Sous PosgreSQL, je n'ai pas réussi à trouver ces fonctionnalités.
Je pense que cela tourne autour de la fonction RAISE ...
La variable SQLSTATE semblerait recevoir le code erreur.
J'ai tenté de l'affecter à une variable de type varchar, mais une erreur est retournée, indiquant SQLSTATE n'est pas une colonne.
Aussi, j'ai besoin d'un petit éclairage de votre part afin de définir une bonne méthode.
Merci de votre retour.
Merci de l'information.
Effectivement, après avoir échappé les $$, le script se déroule correctement.