postgresql 执行由另一个查询创建的查询

jjhzyzn0  于 2023-05-06  发布在  PostgreSQL
关注(0)|答案(2)|浏览(133)

我在包含重叠数据的同一个表上有几个视图。通过从information_schema动态检索视图并将它们联合起来,我可以创建一个文本查询结果。但是,我仍然需要手动运行该查询以获得所需的结果。
这是我用来构建联合查询的查询:

SELECT string_agg('SELECT * FROM '||TABLE_NAME, ' UNION ')::TEXT 
FROM INFORMATION_SCHEMA.VIEWS 
where TABLE_NAME like '%value%'

我最初尝试执行查询并将其存储在临时表中,但尚未成功:

do $$
declare
    q text;
begin
    q := format('SELECT string_agg(''SELECT * FROM ''||TABLE_NAME, '' UNION '')::TEXT FROM INFORMATION_SCHEMA.VIEWS where TABLE_NAME like ''%value%''');
    execute format('create or replace temp view t ', q);
end $$;
select * from t;

如何执行创建的查询并获得实际结果?

qhhrdooz

qhhrdooz1#

psql中的\gexec

如果从默认的命令行终端psql操作(或者从shell调用),可以使用\gexec元命令直接执行动态SQL:

SELECT string_agg('TABLE ' || quote_ident(table_name), ' UNION ')
FROM   information_schema.views
WHERE  table_name LIKE '%value%'
AND    table_schema = 'public'  -- your schema here!
\gexec

在这种情况下不需要临时表。
明确说明模式,否则可能会意外地包含其他对象。
目录表和信息架构视图中列出的标识符可能需要用双引号引起来。quote_ident()或带有指定符%Iformat()负责处理它。否则,您将面临SQL注入!参见:

TABLE my_viewSELECT * FROM my_view的简短语法。参见:

  • 有SELECT * FROM的快捷方式吗?

相关:

  • 模拟PostgreSQL的CREATE DATABASE IF NOT EXISTS?
  • 在源-目标表中生成访问矩阵

纯SQL

否则,我们将回到您的纯SQL方法。修复和改进:

DO
$do$
DECLARE
   _sql text;
BEGIN
   SELECT INTO _sql
          'DROP VIEW IF EXISTS pg_temp.t; CREATE TEMP VIEW t AS '
       || string_agg('TABLE ' || format('%I.%I', table_schema, table_name), ' UNION ')
   FROM   information_schema.views
   WHERE  table_name ~ 'value'
   AND    table_schema = 'public';

   IF _sql IS NOT NULL THEN
      EXECUTE _sql;
   ELSE
      RAISE WARNING 'No views found!';  -- or whatever you need to do here
   END IF;
END
$do$;

TABLE pg_temp.t;  -- table-qualify to make sure

对临时对象进行表限定是一种很好的形式,可以确保您不会意外地以同名的持久化对象为目标。

bakd9h0s

bakd9h0s2#

这里有一个例子(你可以根据需要建立q):
做$$

declare
    q text;
begin
    SELECT 'DROP VIEW IF EXISTS t; CREATE VIEW t AS ' ||  STRING_AGG('SELECT '''||table_name||''' AS col1 ', 'union ') AS dyn_sql
    INTO q
    FROM INFORMATION_SCHEMA.TABLES;
    EXECUTE q;
end $$;
select * from t;

相关问题