在PL / pgSQL中动态执行查询

问题描述 投票:2回答:2

我已经找到了我要在Oracle和SQL Server上解决的问题的解决方案(但我认为),但是似乎无法将其转换为Postgres解决方案。我正在使用Postgres 9.3.6。

想法是能够生成有关表内容的“元数据”以进行概要分析。这只能通过让每一列都运行查询来找出(例如...)最小/最大/计数值等来完成(AFAIK)。为了使过程自动化,最好由数据库生成查询,然后执行。

使用示例salesdata表,我能够使用以下代码段为每列生成一个选择查询,并返回min()值:

SELECT 'SELECT min('||column_name||') as minval_'||column_name||' from salesdata '  
FROM information_schema.columns 
WHERE table_name = 'salesdata'

优点是,无论列数如何,数据库都将生成代码。现在,我想到了无数个地方来存储这些查询,这些查询可以是某种变量,也可以是表列,其想法是执行这些查询。我想到将生成的查询存储在变量中,然后使用EXECUTE(或EXECUTE IMMEDIATE)语句执行它们,这是here所采用的方法(请参见右窗格),但是Postgres不会让我在外部声明变量一个功能,我一直在摸索如何将它们组合在一起,无论这是要遵循的方向,还是有一些更简单的方法。

您有任何指示,我目前正在尝试类似的工作,受other question的启发,但不知道我是否朝着正确的方向前进:

CREATE OR REPLACE FUNCTION foo()
RETURNS void AS
$$
DECLARE
    dyn_sql text; 
BEGIN            
dyn_sql := SELECT 'SELECT min('||column_name||') from salesdata'    
    FROM information_schema.columns 
    WHERE table_name = 'salesdata';
execute dyn_sql
END
$$ LANGUAGE PLPGSQL;    
postgresql aggregate-functions plpgsql dynamic-sql dynamic-queries
2个回答
6
投票

系统统计

您自己滚动之前,请查看系统表pg_statistic或视图pg_statistic

此视图仅允许访问对应的pg_stats行 到用户有权读取的表,因此可以安全地进行 允许公众对此视图进行读取访问。

它可能已经具有您要计算的某些统计信息。它由pg_stats填充,因此您可以在检查之前将其用于新(或任何)表。

pg_statistic

通用动态plpgsql函数

您要返回给定表中每一列的最小值。这不是一件容易的事,因为一个函数(一般来说就是SQL)要求在创建时或在调用时至少在多态数据类型的帮助下知道返回类型。

此功能自动安全地完成所有操作。对于any表有效,只要每一列都允许使用聚合函数ANALYZE。但是您需要了解有关PL / pgSQL的方法。

-- ANALYZE tbl;  -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND   schemaname = 'public';

呼叫(重要!):

min()

db <>小提琴CREATE OR REPLACE FUNCTION f_min_of(_tbl anyelement) RETURNS SETOF anyelement LANGUAGE plpgsql AS $func$ BEGIN RETURN QUERY EXECUTE ( SELECT format('SELECT (t::%2$s).* FROM (SELECT min(%1$s) FROM %2$s) t' , string_agg(quote_ident(attname), '), min(' ORDER BY attnum) , pg_typeof(_tbl)::text) FROM pg_attribute WHERE attrelid = pg_typeof(_tbl)::text::regclass AND NOT attisdropped -- no dropped (dead) columns AND attnum > 0 -- no system columns ); END $func$; SELECT * FROM f_min_of(NULL::tbl); -- tbl being the table name

您需要了解这些概念:

  • 带有here的plpgsql中的动态SQL
  • 多态类型
  • Postgres中的行类型和表类型
  • 如何防范SQL注入
  • 汇总功能
  • 系统目录

具有详细说明的相关答案:

类型不匹配的特殊困难

我利用Postgres为每个现有表定义行类型。使用多态类型的概念,我能够创建适用于任何表的one函数。

但是,与基础列相比,某些聚合函数返回相关但不同的数据类型。例如,Select columns with particular column names in PostgreSQL返回Generate series of dates - using date type as input,它是位兼容的,但<相同的数据类型。 PL / pgSQL函数在这里有一个弱点,并坚持使用min(varchar_column)子句中声明的数据类型exactly。没有尝试转换,甚至没有隐式转换,更不用说任务转换了。应该改善。用Postgres 9.3测试。没用9.4重新测试,但是我很确定,这个区域没有任何变化。

这就是该构造体作为

解决方法

text
通过将整个行显式转换为基础表的行类型,我们强制分配转换以获取每一列的原始数据类型。

这对于某些聚合函数可能会失败。 RETURNSSELECT (t::tbl).* FROM (SELECT ... FROM tbl) t; 返回sum(),以容纳溢出基本数据类型的总和。投射回numeric可能会失败...


0
投票
@@ Erwin Brandstetter,非常感谢您的广泛回答。 pg_stats确实提供了一些东西,但是我真正需要绘制一个完整的配置文件的是各种各样的东西,最小值,最大值,计数,空值计数,均值等...因此必须进行大量查询每列,有些带有GROUP BY等。
© www.soinside.com 2019 - 2024. All rights reserved.