繁体   English   中英

如何在plpgsql中使用变量作为表名

[英]How to use variable as table name in plpgsql

我是 plpgsql 的新手。 我正在尝试使用变量作为 plpgsql 中的表名在 plpgsql 中运行一个简单的查询。 但是变量被解释为表名,而不是被解释为变量名的变量值。

DECLARE
  v_table text;
  z_table text;
  max_id bigint;

BEGIN

FOR v_table IN
    SELECT table_name  
    FROM information_schema.tables 
    WHERE table_catalog = 'my_database' 
    AND table_schema = 'public'
    AND table_name not like 'z_%'
LOOP
    z_table := 'z_' || v_table;
    SELECT max(id) from z_table INTO max_id;
    DELETE FROM v_table where id > max_id;
END LOOP;

一些背景资料。 对于我数据库中的每个表,我都有另一个以“z_”开头的表。 例如,对于一个名为“employee”的表,我有一个名为“z_employee”的相同表。 z_employee包含与员工相同的数据集。 我用它在每次测试开始时恢复员工表。

当我运行此函数时,出现以下错误:

ERROR:  relation "z_table" does not exist
LINE 1: SELECT max(id) from z_table

我的猜测是我不允许在 SQL 查询中使用变量z_table 至少不是我在这里使用它的方式。 但我不知道它应该如何完成。

使用带有EXECUTE动态 SQL,正确地简化和转义标识符:

CREATE OR REPLACE FUNCTION f_test()
  RETURNS void AS
$func$
DECLARE
   v_table text;
BEGIN
   FOR v_table IN
      SELECT table_name  
      FROM   information_schema.tables 
      WHERE  table_catalog = 'my_database' 
      AND    table_schema = 'public'
      AND    table_name NOT LIKE 'z_%'
   LOOP
      EXECUTE format('DELETE FROM %I v WHERE v.id > (SELECT max(id) FROM %I)'
                    , v_table, 'z_' || v_table);
   END LOOP;
END
$func$  LANGUAGE plpgsql;

可能需要引用表名以防止语法错误甚至 SQL 注入! 我使用方便的format()来连接DELETE语句并正确转义标识符。

  • 单独的SELECT会更贵。 您可以使用单个DELETE语句完成所有操作。

有关的:

在旁边:

您可以使用(稍微快一点)系统目录pg_tables代替:

      SELECT tablename
      FROM   pg_catalog.pg_tables
      WHERE  schemaname = 'public'
      AND    tablename NOT LIKE 'z_%'

看:

information_schema.tables中的table_catalog在这里没有等效项。 无论如何,只有当前数据库的表是可见的。 所以当连接到错误的数据库时,上面的谓词WHERE table_catalog = 'my_database'会产生一个空的结果集。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM