如何在函数中按顺序对表列表运行 ALTER TABLE

dd_*_*d_a 2 postgresql dynamic-sql alter-table plpgsql functions

我有一个模式(称为import),其中数据作为表导入,以及一个处理它们的函数。之后我想将这些表移到另一个模式中(称为data_archive)中。现有功能运行良好,但我找不到更改架构的方法;这是我编写的一个函数:

我的想法是根据selecta 为该管理制作的表格提供的标准创建表格列表,然后遍历此列表并执行以下操作Alter table xxxx SET schema data_archive

CREATE OR REPLACE FUNCTION archive_datasets()
  RETURNS VOID AS
$BODY$
DECLARE
   table_rec  record;

BEGIN

   FOR table_rec IN
      SELECT t.table_name
      FROM information_schema.tables AS t
      WHERE table_schema = 'import'
      AND quote_ident(t.table_name) IN (
              SELECT "table_name"
              FROM data_sets 
              WHERE status IN ('Processed', 'Archived', 'Deleted')
              ) 

   LOOP
     ALTER TABLE quote_ident(table_rec.table_name) SET schema data_archived;
   END LOOP;

END;
$BODY$
  LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

但我收到此错误消息:

ERROR:  syntax error at or near "("
LINE 28:  ALTER TABLE quote_ident(table_rec.table_name) SET schema ...
Run Code Online (Sandbox Code Playgroud)

所以我的问题是如何将表名传递给这个ALTER TABLE查询?或者我做错了什么?

我使用 PostgreSQL 9.3。

dez*_*zso 6

问题是你不能像ALTER TABLE上面那样在直接的 SQL 语句中使用参数作为对象名称(表、列等)。

我在这里使用“直接”作为“动态”的对立面——你需要的东西:

...
loop
    EXECUTE format($$ALTER TABLE %I SET SCHEMA TO data_archived$$, 
                   table_rec.table_name);
END loop;
...
Run Code Online (Sandbox Code Playgroud)

注意事项

  • 在这里,我在构建动态查询时使用美元引用。例如,这允许我使用“普通”语法,而不是乘以单引号(本示例中不存在)。这样,大多数编辑将很好地突出显示语句。
  • 我也使用format()%I格式说明有必要时对象名称正确引用。这种方法比用字符串常量和一些quote_ident()调用的串联构建查询更具可读性。它存在于版本 9.1 和更新版本中。
  • 我有一种感觉,你比较像quote_ident('This_table') IN ('This_table'),这不会是真的。要么quote_ident()在两侧使用- 要么更容易省略引用并比较字符串值。