web-dev-qa-db-fra.com

Pour sélectionner de toutes les tables à l'intérieur du schéma dans PostgreSQL

Est-il possible de choisir parmi toutes les tables à l'intérieur du schéma? J'ai eu tous les noms de table de

select table_name from information_schema.tables

mais je suis incapable de l'utiliser pour faire ma requête.

7
Stat-R

Vous ne pouvez pas le faire directement car on ne peut pas écrire une requête "normale" si les noms de table ne sont pas connus (c'est-à-dire provenant d'une variable ou d'une sous-requête). Mais vous pouvez construire et exécuter une instruction SQL dynamique pour cela. Par exemple, si vous avez besoin de la colonne 'Nom' de chaque table, vous pouvez effectuer ce qui suit (à l'intérieur d'une fonction PL/PGSQL ):

FOR i IN SELECT table_name 
           FROM information_schema.tables 
          WHERE table_schema = 'your_desired_schema'
LOOP
    sql_string := sql_string || format($$
        -- some whitespace is mandatory here
        UNION
        SELECT name FROM %I
    $$,
    i.table_name);
END LOOP;

EXECUTE sql_string;

Dans ce formulaire, cela ne fonctionnera cependant pas, car vous ne pouvez pas SELECT in plpqsql si vous ne le faites pas dans une variable. Vous pouvez créer une table temporaire pour cela, en boucle sur les résultats (dans une autre FOR boucle) ou - sans utiliser UNION - juste revenir dans chaque itération, en fonction de vos besoins.

Et, bien sûr, cela suppose que vous souhaitez sélectionner une colonne unique (ou plusieurs, mais toujours avec le même nom et le même type) de toutes les tables. Si vous avez simplement besoin de toutes les données de chaque table, les tables doivent avoir la même structure (les mêmes types de colonnes dans le même ordre, avec les mêmes noms).

Remarques:

  • la fonction format() a été introduite dans la version 9.1
  • J'ai omis des éléments obligatoires de tout bloc PL/PGSQL pour le garder simple
  • la version antérieure mentionnée à l'aide d'un bloc DO. Le problème avec c'est que vous ne pouvez pas simplement utiliser SELECT là-bas pour retourner des lignes, car elle a été signalée dans une autre réponse .
4
dezso

OK, il est vraiment en retard, mais j'ai eu le même problème à résoudre et j'ai réussi à le résoudre et retourner toutes les lignes de toutes les tables sous un schéma spécifique à l'aide d'un FUNCTION comme DO ne fonctionnait pas pour Moi, malheureusement suggéré des réponses ne fonctionnaient pas vraiment, comme en utilisant DO ne retournait rien, voici mon FUNCTION:

CREATE OR REPLACE FUNCTION union_all_tables()
  RETURNS TABLE
          (
            id        integer,
            full_name varchar(100),
            col3      varchar(200),
            col4      numeric,
            col5      char,
            version   bigint
          ) AS
$$
DECLARE
  dynamic_query text = '';
  r_row         record;
BEGIN
  FOR r_row IN SELECT table_schema || '.' || table_name qualified_table_name
               FROM information_schema.tables
               WHERE table_schema = 'staging'
                 AND table_name LIKE '%_postfix'
    LOOP
      dynamic_query := dynamic_query || format('UNION SELECT ' ||
                                               'id, ' ||
                                               'full_name, ' ||
                                               'col3, ' ||
                                               'col4, ' ||
                                               'col5, ' ||
                                               'version ' ||
                                               'FROM %s ', r_row.qualified_table_name) || E'\n'; -- adding new line for pretty print, it is not necessary
    END LOOP;

  -- before we execute the query, we need to remove first "UNION " from the string
  dynamic_query := SUBSTRING(dynamic_query, 7) || ';';

  -- printing the statement as a notice so you know that the statement is in a good format, 
  -- or you can copy paste it and try it in the console to know if that statement is working or not. 
  RAISE NOTICE 'Union all tables in staging, executing statement: %', dynamic_query;
  RETURN QUERY EXECUTE dynamic_query;
END;
$$
  LANGUAGE plpgsql;

Notez que j'ai ajouté AND table_name LIKE '%_postfix' Ici si vous avez eu une convention de nommage et que vous souhaitez enregistrer des maux de tête pour cela, si vous ne le voulez pas, supprimez-le, notez également que si vous voulez faire UNION toutes les tables doivent suivre la même chose. Structure, sinon vous sélectionnez les colonnes communes que vous souhaitez (et ceci est mon cas ici dans ma solution), sinon si vous voulez toutes les colonnes, il a besoin d'un script plus complexe pour cela.

Cette solution travaillant pour moi dans PostgreSQL 10 et 11.

1
Al-Mothafar