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 20/10/2017 16:03:28

Mlan2
Membre

SQL Dynamique - Création de table

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

#2 20/10/2017 18:46:21

gleu
Administrateur

Re : SQL Dynamique - Création de table

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

#3 23/10/2017 09:12:35

Mlan2
Membre

Re : SQL Dynamique - Création de table

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

#4 23/10/2017 16:44:05

rjuju
Administrateur

Re : SQL Dynamique - Création de table

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.

Hors ligne

#5 23/10/2017 16:56:09

Mlan2
Membre

Re : SQL Dynamique - Création de table

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

#6 23/10/2017 17:23:49

rjuju
Administrateur

Re : SQL Dynamique - Création de table

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.

Hors ligne

#7 23/10/2017 22:28:52

gleu
Administrateur

Re : SQL Dynamique - Création de table

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

Pied de page des forums