PLPGSQL;将所有表名存储到数组中

时间:2013-12-05 10:53:38

标签: sql postgresql plpgsql

我的主要目的实际上是,过滤所有表名称中包含“Messdaten”(例如“ID:843063334 CH:0001 Messdaten”)并使用“create table as”命令创建新表格作为“Backup_Messdaten1” ,'Backup_Messdaten2'等

首先,我试图存储所有表名而不进行过滤(可能有一种方法可以检索所有表名,通过sql查询包含'Messdaten',我不知道),然后存储包含' Messdaten'进入另一个数组并在'create table as'命令中使用该新数组。

但正如我所说,我的第一个目标是将所有表名存储到一个数组中;

代码本身;

CREATE OR REPLACE FUNCTION retrieve()
RETURNS text[] AS
$BODY$DECLARE
tbl_names text[];
BEGIN
tbl_names := array(SELECT table_name FROM information_schema.tables WHERE 
table_schema='public' AND table_type='BASE TABLE');
SELECT tbl_names[i] FROM generate_subscripts(tbl_names, 1) g(i);
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION retrieve()
OWNER TO postgres;

但是对于上面的代码,我收到了这样的错误;

错误;

ERROR: could not find array type for data type information_schema.sql_identifier
SQL state: 42704
Context: SQL statement "SELECT array(SELECT table_name FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE')"
PL/pgSQL function retrieve() line 4 at assignment

你知道它有什么问题吗?通过我解释我的主要目的的方式,如果你指出我正确的方向,我会很感激。

2 个答案:

答案 0 :(得分:3)

SELECT array_agg(table_name::text)
FROM information_schema.tables
WHERE table_schema='public' AND table_type='BASE TABLE';

您需要将表名转换为text。子查询是不必要的,您需要使用array_agg而不是array伪函数。

我个人认为你不明白为什么需要将它们聚合成一个数组。我只是:

DECLARE
    tablename text;
BEGIN
    FOR tablename IN
      SELECT table_name FROM information_schema.tables
      WHERE table_schema='public' AND table_type='BASE TABLE'
      AND ... my extra filters here ...
    LOOP
        EXECUTE format('CREATE TABLE %I AS TABLE %I', tablename || '_backup', tablename);
    END LOOP;
END;

答案 1 :(得分:2)

您的代码包含更多错误 - 基本错误缺少任何RETURN语句(对于PL / pgSQL语言)。您也可以使用SQL语言(参见我的示例)

Postgres不支持某些类型的数组 - sql_identifier是一个。您可以尝试将转换用于某种基本类型 - 在本例中为文本。

CREATE OR REPLACE FUNCTION names(filter text)
RETURNS text[] AS $$
   SELECT array_agg(table_name::text)
      FROM information_schema.tables
     WHERE table_schema='public'
       AND table_type='BASE TABLE' AND table_name LIKE $1;
$$ LANGUAGE sql;

postgres=# select names('foo%');
   names    
------------
 {foo1,foo}
(1 row)