在PostgreSQL中,是否可以查询给定数据库中的所有表?

时间:2019-04-23 17:53:12

标签: sql postgresql

在PostgreSQL中,是否可以查询给定数据库中的所有表以获得满足某些条件的记录?

Select [dbname "db"] *
From [all tables in database "db"]
Where [some condition on records]

[]中的内容是任意的,直到它们通常应具有的含义为止。

谢谢。

1 个答案:

答案 0 :(得分:2)

这里最好的选择是,您希望返回特定数据库中满足特定条件的每个表的所有行。这变得棘手,因为:

  1. 在您查询的每个表中都必须存在您的条件所基于的表。
  2. 此外,由于您在一个模式/数据库中的许多表可能具有不同的列,因此您无法在相同的结果集中全部返回它们。
  3. 没有可以发送到数据库的“一个” sql语句来执行此操作。您将至少查询两次。一次获取表列表,再一次查询这些表。

考虑一个包含两个表的数据库/方案,两个表的列都为F1。我们希望该模式中F1=1中的表中的所有记录。所以:

# CREATE TABLE public.t2 (f1 int, f2 varchar(20), f3 date);
    CREATE TABLE
# CREATE TABLE public.t1 (f1 int, f4 varchar(40), f5 varchar(10), f6 int);
    CREATE TABLE
# SELECT * FROM information_schema.tables WHERE table_schema = 'public';
     table_catalog | table_schema | table_name | table_type | self_referencing_column_name | reference_generation | user_defined_type_catalog | user_defined_type_schema | user_defined_type_name | is_insertable_into | is_typed | commit_action 
    ---------------+--------------+------------+------------+------------------------------+----------------------+---------------------------+--------------------------+------------------------+--------------------+----------+---------------
     username      | public       | t2         | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
     username      | public       | t1         | BASE TABLE |                              |                      |                           |                          |                        | YES                | NO       | 
    (2 rows)

# SELECT 'SELECT * FROM public.' || table_name || ' WHERE f1=1;' FROM 
    information_schema.tables WHERE table_schema = 'public';
                  ?column?               
    -------------------------------------
     SELECT * FROM public.t2 WHERE f1=1;
     SELECT * FROM public.t1 WHERE f1=1;
    (2 rows)

最后一条SQL生成两条记录(对于架构中的每个表一条记录),查询它的条件为true的记录。现在,您可以分别执行每个操作以获取结果(在两个结果集中)。

# SELECT * FROM public.t2 WHERE f1=1;SELECT * FROM public.t1 WHERE f1=1;
     f1 | f2 | f3 
    ----+----+----
    (0 rows)

     f1 | f4 | f5 | f6 
    ----+----+----+----
    (0 rows)

如果架构中的每个表都完全相同(相同的列数,列的顺序和数据类型),则可以查询information_Schema并构建一个UNION查询,然后分别执行:

# CREATE TABLE public.t1 (f1 int, f2 varchar(20), f3 date);
    CREATE TABLE
# CREATE TABLE public.t2 (f1 int, f2 varchar(20), f3 date);
    CREATE TABLE
# INSERT INTO public.t1 VALUES (1, 'test', '2019-04-22'),(2, 'test2', '2019-04-22');
    INSERT 0 2
# INSERT INTO public.t2 VALUES (1, 'testtest', '2019-04-21'),(2, 'testest2', '2019-04-20');
    INSERT 0 2
# SELECT 'SELECT * FROM public.' || table_name || ' WHERE f1=1' || CASE WHEN LEAD(table_name) OVER (ORDER BY table_name) IS NOT NULL THEN ' UNION ALL' ELSE ';' END FROM information_schema.tables WHERE table_schema = 'public';
                       ?column?                   
    ----------------------------------------------
     SELECT * FROM public.t1 WHERE f1=1 UNION ALL
     SELECT * FROM public.t2 WHERE f1=1;
    (2 rows)
# SELECT * FROM public.t1 WHERE f1=1 UNION ALL
-#  SELECT * FROM public.t2 WHERE f1=1;
     f1 |    f2    |     f3     
    ----+----------+------------
      1 | test     | 2019-04-22
      1 | testtest | 2019-04-21
    (2 rows)

您可以看到这两个选项都不是很漂亮,因为您必须动态编写SQL,然后分别执行它。