Vous n'êtes pas identifié(e).
Pages : 1
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.
Hors ligne
Si le code génère des erreurs, ce serait sympa de fournir l'erreur en question. Ça permettrait de vous aider sans jouer aux devinettes. Bref, en créant la table matablea, voici le message d'erreur renvoyé :
ERROR: EXECUTE of SELECT ... INTO is not implemented
HINT: You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.
CONTEXT: PL/pgSQL function inline_code_block line 10 at EXECUTE
Ce qui semble s'expliquer clairement. Vu que l'idée est de créer une table, il faut utiliser un EXECUTE CREATE TABLE ... AS.
Guillaume.
Hors ligne
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.
Hors ligne
Pourquoi voulez-vous générer un bloc de code anonyme au milieu d'une procédure stockée ?
De plus, la syntaxe "IF EXISTS(...) THEN" n'est pas compatible sur postgres.
Julien.
https://rjuju.github.io/
Hors ligne
Merci du retour,
La fonction envisagée doit assurer la suppression d'une table passée en paramètre.
La présence de la clause : IF EXISTS se justifie pleinement car le drop d'une table inexistante provoque une erreur.
Cela me parait plus propre de faire ce contrôle préalable.
J'ai utilisé un bloc de code anonyme pour la raison suivante : La clause EXECUTE n'autorise pas l'exécution de IF EXISTS (erreur de syntaxe).
A moins que je me trompe.
D'avance merci de vos prochains retours.
Hors ligne
Je suis d'accord qu'il ne faut pas faire aveuglément un simple drop table, mais sur postgres il suffit de faire « DROP TABLE IF EXISTS nom_table » pour supprimer une table si elle existe.
Du coup, je ne sais pas si vous avez vraiment le besoin d'une procédure stockée ou non.
Au passage, j'attire votre attention que vous ne qualifiez pas le nom de la table, cela pourrait être problématique si un même nom de table existe dans différents schéma.
Julien.
https://rjuju.github.io/
Hors ligne
Pour vous donner une idée de ce à quoi devrait ressembler le code de cette fonction :
create or replace function recreate_table (p_nomtable text) returns boolean language plpgsql
as $$
declare
sql text;
begin
perform 1 from pg_class where relname=p_nomtable and relkind='r';
if found then
sql := 'drop table '||quote_ident(p_nomtable);
execute sql;
end if;
sql := 'create table '||quote_ident(p_nomtable)||' (id integer)';
execute sql;
return true;
end;
$$;
Comme le dit Julien, il faudrait le changer pour faire attention au schéma mais l'idée est là.
Guillaume.
Hors ligne
Pages : 1