在 PL/pgSQL 中动态执行查询

2023-12-12

我已经找到了我在 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 (or EXECUTE IMMEDIATE) 所采用的方法的声明here(参见右窗格),但是 Postgres 不允许我在函数外部声明变量,我一直在绞尽脑汁地思考如何将其组合在一起,无论这是否是要遵循的方向,也许有更简单的东西。

您有任何指示吗,我目前正在尝试类似的事情,受到此启发其他问题但不知道我是否朝着正确的方向前进:

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;    

系统统计

在你自己动手之前,先看看系统表pg_statistic或视图pg_stats:

该视图仅允许访问行pg_statistic对应的 用户有权读取的表,因此是安全的 允许公共读取此视图。

它可能已经有一些您要计算的统计数据。它的人口由ANALYZE,因此您可以在检查之前对新(或任何)表运行该命令。

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

通用动态 plpgsql 函数

您想要返回给定表中每列的最小值。这不是一项简单的任务,因为函数(通常像 SQL)需要在创建时知道返回类型 - 或者至少在多态数据类型的帮助下在调用时知道返回类型。

该功能自动且安全地完成所有操作。效劳于any表,只要聚合函数min()每列都允许。但是你need了解 PL/pgSQL 的方法。

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
Old sqlfiddle

你需要理解这些概念:

  • plpgsql 中的动态 SQLEXECUTE
  • 多态类型
  • Postgres 中的行类型和表类型
  • 如何防御SQL注入
  • 聚合函数
  • 系统目录

相关答案及详细解释:

  • 表名作为 PostgreSQL 函数参数
  • 重构 PL/pgSQL 函数以返回各种 SELECT 查询的输出
  • Postgres 数据类型转换
  • 如何使用动态SQL设置复合变量字段的值
  • 如何检查给定模式中是否存在表
  • 在 PostgreSQL 中选择具有特定列名的列
  • 生成一系列日期 - 使用日期类型作为输入

类型不匹配的特殊困难

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

但是,与基础列相比,某些聚合函数返回相关但不同的数据类型。例如,min(varchar_column)回报text,这是位兼容的,但不是exactly相同的数据类型。 PL/pgSQL 函数在这里有一个弱点,并且坚持数据类型exactly正如声明中所宣布的RETURNS条款。没有尝试强制转换,甚至没有隐式强制转换,更不用说赋值强制转换了。

这一点应该改进。使用 Postgres 9.3 进行测试。没有用 9.4 重新测试,但我很确定,这方面没有任何改变。

这就是这个构造的用处解决方法:

SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;

通过显式地将整行转换为基础表的行类型,我们强制赋值转换以获得每列的原始数据类型。

对于某些聚合函数,这可能会失败。sum()回报numeric for a sum(bigint_column)以适应溢出基本数据类型的总和。投射回bigint可能会失败...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 PL/pgSQL 中动态执行查询 的相关文章

随机推荐

  • 使用 JQgrid 和 sortableRows。更新表行顺序

    Using 使用 SortableRows 并了解行何时被移动修改行顺序后 我已经能够调用警报 我如何将此数据发送到 PHP 调用 editurl 传递此数据 类似于添加或编辑行时 editurl 接收 POST oper 变量 目前有 j
  • 从堆执行指令

    我可以在堆上分配一个块 将其字节设置为与函数调用及其参数相对应的值 然后使用函数调用和取消引用运算符来执行该序列吗 因此 如果我没理解错的话 您想在堆上动态创建 CPU 汇编指令并执行它们 有点像自修改代码 理论上这是可能的 但实际上可能不
  • 使用 Python 修复 Selenium Form 的等待时间

    我是 Python 新手 正在尝试自动填写表单 我已经完成了所有工作 但是当尝试 提交 时 它没有读取 XPATH 因此没有单击 HTML
  • 如何获取操作的默认应用程序

    如何确定哪个应用程序是特定操作的默认应用程序 例如我想知道哪个应用程序用于拨打电话或接收短信 有什么方法可以以编程方式找出哪个应用程序设置为默认应用程序 PackageManager resolveActivity做一些符合您正在寻找的事情
  • 自定义声音远程推送通知 iOS 不起作用

    我正在尝试更改远程消息的声音 我已将文件添加到我的项目中 见图1 我还将所有内容添加到我的 AppDelegate 中 在 didFinishLaunchingWithOptions 中我添加了 if UIDevice currentDev
  • 即使添加 -fPIC 编译标志后,“使用 -fPIC 重新编译”错误仍然存​​在

    我已经下载了一些我想从源代码编译的 C 运行后cmake src进而make从命令行 在构建目录中 我收到以下错误 usr bin ld usr local lib libBulletCollision a btDbvtBroadphase
  • 寄存器的十六进制值? x86

    MOV DL AL MOV DL B2 但是 AL 的十六进制字节值是多少 这些在哪里列出 我刚刚意识到这一定是另一个操作码 有人能指出我正确的方向吗 来自英特尔架构软件开发人员手册 第 2 卷 指令集参考手册 表3 1 与 rb rw 和
  • 即使身份验证成功,PassportJS Facebook 登录 isAuthenticated 返回 false

    由于某种原因 在我的 NodeJS Express 应用程序上 当通过 PassportJS 库与 Facebook 进行身份验证时 无论身份验证是否成功并返回配置文件数据 都会调用request isAuthenticated 总是回来f
  • 如何自动检测串行COM端口的连接C#

    我有与设备通信的应用程序 设备通过串行 COM 端口连接 我的应用程序可以与设备通信 我需要一些方法 事件 可以通过运行应用程序扫描COM端口 当我将设备连接到 PC 时 方法 事件将打印带有消息 已连接 或类似内容的 MessageBox
  • 当焦点从 EditText 更改为 Button 时 ActionBarSherlock 操作栏消失

    我有一个简单的登录布局 其中包含两个 EditText 字段和一个用于登录的按钮 问题是 当软键盘打开并且我将焦点从 EditText 更改为按钮时 ActionBar 消失 当我按返回时 ActionBar 再次返回 当软键盘关闭并且我使
  • Sass mixin 添加到选择器前面

    是否可以制作一个 SASS mixin 将其输出添加到选择器之前 我用现代化检查浏览器的 svg 功能 它输出svg类到支持 svg 时的元素 我想要background image根据 svg 功能进行更改 基本上 这就是我所需要的 co
  • 在 jQuery 的 Deferred 对象中抛出错误

    我有一个 ajax承诺并想要检查我的 语法上有效的 响应是否包含错误 在这种情况下触发拒绝状态 我使用了自己的承诺库 它可以轻松处理此类任务 我不太喜欢 jQueryPromise cache 实施及其Deferred object可能忽略
  • Discord.py:使用变量作为 Discord 嵌入颜色

    所以我试图为我的不和谐机器人 一个嵌入构建器 发出一个命令 我希望命令的用户能够输入嵌入颜色的十六进制值 这是我尝试过的 value message content embed discord Embed title Hey descrip
  • 为什么 didSet 中没有无限循环?

    在我的 FirstViewController 中 我有一个指向 SecondViewController 的按钮 将数据传递到 SecondViewController 中的属性 该属性有一个属性观察者 在设置时创建 SecondView
  • Golang 将数组传递给函数并修改它

    在大多数语言 如 C 中 传递数组会导致通过引用隐式传递数组 因此对函数中传递的数组的任何更改都将导致原始数组的更改 我正在学习 Golang 在 Alan A A 的 Go 编程语言 一书中Donovan 和 Brian W Kernig
  • 在 SSRS 中,如何使用多值参数创建动态“where”条件

    首先我会提到一些我的工作以更好地理解我的问题 因此 在 SSRS 中 我有多个参数 所有这些参数都使用以下命令发送到过程 Join Parameter x value 然后在过程中我通过连接所有参数创建一个 where 条件 像这样的东西
  • 更改 Reveal.js 中的背景图像样式

    我尝试访问 Reveal js 中背景图像的样式有以下三个原因 a 我想在概览模式下覆盖背景图像 b 我想用 CSS 模糊一些背景 我发现两篇关于 SO 的文章对我有帮助 a 如何在reveal js中定位背景图片 b Reveal js
  • Azure Pipeline - 使用模板任务中设置的变量作为另一个模板任务中的参数

    我创建了两个模板 一个用于获取和设置一些配置 例如区域名称 另一个用于部署 我尝试使用配置模板任务中设置的变量作为部署模板的参数输入 有没有实际的方法可以做到这一点 我的配置模板 steps task AzureCLI 2 name Con
  • 如何在GCC trunk中使用

    From https github com gcc mirror gcc commit 3acb929cc0beb79e6f4005eb22ee88b45e1cbc1d提交 C 标准头
  • 在 PL/pgSQL 中动态执行查询

    我已经找到了我在 Oracle 和 SQL Server 上提出的问题的解决方案 我认为 但似乎无法将其转换为 Postgres 解决方案 我正在使用 Postgres 9 3 6 这个想法是能够生成有关表内容的 元数据 以用于分析目的 这