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 Re : PL/pgSQL » Lister les lignes de toutes les tables ayant une valeur spécifique » 25/09/2024 15:47:40

Bonjour,
j'ai mis le temps (j'ai fait d'autres choses quand même entre temps lol) mais j'ai réussi à faire la fonction que je voulais.
Ci-dessous, le code final de la fonction (les noms de variables ont changés) avec un exemple de select correspondant.
Merci.

CREATE OR REPLACE FUNCTION get_table_row_ids(sch text, prj text)
RETURNS TABLE (tablename text, row_id int) LANGUAGE plpgsql AS $$
BEGIN
    -- Boucle sur les tables du schéma spécifié
    FOR tablename IN
        SELECT table_name
        FROM information_schema.columns
        WHERE table_schema = sch 
          AND column_name = 'PRJ_UUID'
          AND table_name NOT LIKE 'SYS_%'
        ORDER BY table_name
    LOOP
        -- Requête dynamique pour récupérer les IDs
        FOR row_id IN
            EXECUTE format('SELECT id FROM %I.%I WHERE "PRJ_UUID" = %L', sch, tablename, prj)
        LOOP
            -- Retourner chaque ligne trouvée
            RETURN NEXT;
        END LOOP;
    END LOOP;
END $$;
SELECT * FROM get_table_row_ids('route', 'fc06279b-121b-463e-9409-87bb5eb6cc0b'); -- sch et prj à modifier

#2 Re : PL/pgSQL » Lister les lignes de toutes les tables ayant une valeur spécifique » 27/06/2024 10:21:45

Merci rjuju pour tes énignes big_smile
J'ai complété le code au vu de ce que j'ai pu comprendre mais cela me renvoie une erreur par rapport au type de la variable tbl qui est record et qui n'est pas compatible avec next, mais si je la met en text elle n'est plus reconnu dans ma 2ème boucle.
Bref je sèche une fois de plus.
Merci par avance.

DROP TABLE IF EXISTS liste_rubrique_prj CASCADE;
CREATE TABLE liste_rubrique_prj(l_table_name TEXT, l_row_id TEXT);

CREATE OR REPLACE FUNCTION get_liste_rubrique_prj()
RETURNS SETOF liste_rubrique_prj
LANGUAGE plpgsql
AS $$
DECLARE
    sch text := 'route';
    tbl record;
    line record;
    prj text := 'fc06279b-121b-463e-9409-87bb5eb6cc0b';
BEGIN
    FOR tbl IN
        SELECT table_name
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE table_schema = sch AND column_name = 'PRJ_UUID' AND table_name not like 'SYS_%'
        ORDER BY table_name
    LOOP
        FOR line IN
            EXECUTE 'SELECT id
            FROM '|| sch || '."' || tbl.table_name ||'"
            WHERE "PRJ_UUID" = '''|| prj ||''''
        LOOP
            INSERT INTO liste_rubrique_prj(l_table_name,l_row_id) VALUES (tbl.table_name,line.id);
        END LOOP;
    RETURN NEXT tbl;
    END LOOP;
    RETURN;
END $$;

SELECT * FROM get_liste_rubrique_prj();

#3 Re : PL/pgSQL » Lister les lignes de toutes les tables ayant une valeur spécifique » 25/06/2024 11:09:08

Bonjour,

j'avais mis le sujet de côté et après avoir fait des recherches sur les fonctions suite à ta réponse, je suis arrivé à un code qui ne renvoie pas d'erreur mais pas de résultat non plus.
Peux-tu me dire que qui est mal écrit ?
Merci par avance pour tes lumières big_smile

CREATE OR REPLACE FUNCTION list_rubric(anyelement)
RETURNS anyarray language plpgsql AS $$
DECLARE
    sch text := 'route';
    tbl record;
    row_id record;
    prj text := 'fc06279b-121b-463e-9409-87bb5eb6cc0b';
BEGIN
    FOR tbl IN
        SELECT table_name
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE table_schema = sch AND column_name = 'PRJ_UUID' AND table_name not like 'SYS_%'
        ORDER BY table_name
    LOOP
        FOR row_id IN
            execute 'SELECT id
            FROM '|| sch || '."' || tbl.table_name ||'"
            WHERE "PRJ_UUID" = '''|| prj ||''''
        LOOP
            SELECT tbl.table_name, row_id.id;
        END LOOP;
    END LOOP;
END $$;

#4 Re : PL/pgSQL » Lister les lignes de toutes les tables ayant une valeur spécifique » 05/06/2024 10:29:49

Merci rjuju pour ta réponse.
Je ne connaissais pas RAISE NOTICE du coup j'ai fait des recherches et suis arrivé au code suivant.
C'est peut-être pas le meilleur niveau sémantique mais ça fonctionne big_smile

DO $$
DECLARE
    sch text := 'route';
    tbl record;
    row_id record;
    prj text := 'fc06279b-121b-463e-9409-87bb5eb6cc0b';
BEGIN
    FOR tbl IN
        SELECT table_name
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE table_schema = sch AND column_name = 'PRJ_UUID' AND table_name not like 'SYS_%'
        ORDER BY table_name
    LOOP
        FOR row_id IN
            execute 'SELECT id
            FROM '|| sch || '."' || tbl.table_name ||'"
            WHERE "PRJ_UUID" = '''|| prj ||''''
        LOOP
            RAISE NOTICE 'Table: % - Id: %', tbl.table_name, row_id.id;
            END LOOP;
    END LOOP;
END $$;

Mon seul regret est de n'avoir pas réussi à avoir le résultat sous forme de tableau, mais je crois qu'il faut faire un CREATE TEMP TABLE.
C'est bien ça ?
Encore merci pour ton aide.

#5 PL/pgSQL » Lister les lignes de toutes les tables ayant une valeur spécifique » 03/06/2024 16:38:17

Arnaud_CX
Réponses : 7

Bonjour à tous,

comme indiqué, je souhaite lister toutes les tables de mon schéma 'route' qui ont un champ 'PRJ_UUID' et dont la valeur de ce champ peut prendre différentes valeurs.

Après beaucoup de recherche j'arrive à faire la liste de toutes les tables avec ce champ (on ne rigole pas big_smile)

SELECT table_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_schema = 'route' AND column_name = 'PRJ_UUID'
ORDER BY table_name

mais quand j'intègre ce select dans un loop, ça se gâte. Voici le code que j'utilise :

DO
$do$
DECLARE
  sch text := 'route';
  tbl text;
BEGIN
  FOR tbl IN
    SELECT table_name
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE table_schema = sch AND column_name = 'PRJ_UUID'
  LOOP
    EXECUTE format($$SELECT "id" FROM %I.%I WHERE "PRJ_UUID" = 'fc06279b-121b-463e-9409-87bb5eb6cc0b'
    $$, sch, tbl);
  END LOOP;
END
$do$;

je n'ai pas d'erreur mais je n'ai pas de résultat non plus, alors que je sais qu'il existe.

Pouvez-vous me dire ce qui cloche.
Merci par avance.

#6 Re : PL/pgSQL » Conditions dans loop » 28/09/2021 16:38:22

Après avoir retourné le problème dans tous les sens, l'erreur est toute bête.
Il faut simplement mettre %% à la place de % comme indiqué dans le résultat d'erreur roll

Merci rjuju pour le placement du CASE car je ne savais pas comment faire.

#7 Re : PL/pgSQL » Conditions dans loop » 28/09/2021 14:51:09

Merci pour votre retour.

Quelle condition exactement?  Vous n'avez aucune clause where donc la mise à jour va s'effectuer sur toutes les lignes, que le contenu change ou non.

Si la route contient un 'G' ça le remplace par '_G'

Utiliser ce CASE dans votre SET "ROUTE" ne fonctionne pas ?  Quelle est l'erreur ?

En integrant CASE dans SET ci-dessous :

DO
$do$
DECLARE
    sch text := 'test';  -- your schema here
    tbl text;
BEGIN
	FOR tbl IN
		SELECT tablename FROM pg_catalog.pg_tables
		WHERE  schemaname = sch
	LOOP
		EXECUTE format($$UPDATE %I.%I SET "ROUTE" = 
		
			CASE
				WHEN "ROUTE" = '10 D0001G' THEN '10 D0001G'
				WHEN "ROUTE" LIKE '%G%' THEN replace ("ROUTE" , 'G', '_G')
				WHEN "ROUTE" LIKE '%E_%' THEN REPLACE ("ROUTE" , 'E', '_E')
				WHEN "ROUTE" LIKE '%B_' THEN REPLACE ("ROUTE" , 'B', '_B')
				ELSE "ROUTE"
			END		
		
		$$, sch, tbl);
	END LOOP;
END
$do$;

J'ai l'erreur :

ERREUR: spécificateur de type « G » pour format() non reconnu
HINT:  Pour un unique "%" utilisez "%%".
CONTEXT:  fonction PL/pgsql inline_code_block, ligne 1 à EXECUTE

sad sad sad

#8 PL/pgSQL » Conditions dans loop » 28/09/2021 12:54:04

Arnaud_CX
Réponses : 3

Bonjour,

je dois remplacer les valeurs du champ "ROUTE" champ dans toutes les tables  du schéma "test".

Ma requête est :

DO
$do$
DECLARE
    sch text := 'test';
    tbl text;
BEGIN
    FOR tbl IN
        SELECT tablename FROM pg_catalog.pg_tables
        WHERE  schemaname = sch
    LOOP
        EXECUTE format($$UPDATE %I.%I SET "ROUTE" = replace("ROUTE", 'G', '_G')$$, sch, tbl);
    END LOOP;
END
$do$;

Mais ça remplace toutes les routes remplissant cette condition.
En réalité, ma requête dois remplir toutes les conditions suivantes mais je n'arrive pas à imbriquer les 2 codes.

CASE
WHEN "ROUTE" = '10 D0001G' THEN '10 D0001G'
WHEN "ROUTE" LIKE '%G%' THEN replace ("ROUTE" , 'G', '_G')
WHEN "ROUTE" LIKE '%E_%' THEN REPLACE ("ROUTE" , 'E', '_E')
WHEN "ROUTE" LIKE '%B_' THEN REPLACE ("ROUTE" , 'B', '_B')
ELSE "ROUTE"
END

Savez-vous comment faire ?
Merci par avance pour votre aide.

Pied de page des forums

Propulsé par FluxBB