2013-12-05 5 views
1

Моя основная цель - на самом деле фильтрация всех имен таблиц содержит в ней «Messdaten» (например, «ID: 843063334 CH: 0001 Messdaten») и создавать из них новые таблицы с помощью «create table as 'command as' Backup_Messdaten1 ',' Backup_Messdaten2 'и т. д.Plpgsql; хранить все имена таблиц в массиве

Сначала я пытался хранить все имена таблиц без фильтрации (возможно, есть способ получить все имена таблиц, содержать «Messdaten» в нем по запросу sql, Я не знаю), а затем их хранение содержит «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 

У вас есть какие-либо идеи, что случилось с ним и, кстати, я объяснил свою основную цель, я был бы признателен, если вы мне точку в правильном направлении относительно этой цели.

ответ

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; 
+0

спасибо, сейчас он работает. На самом деле не было никакой возможности объединить их в массив, я просто подумал, что это единственный способ. Мне нужно прочитать больше руководства, я думаю =) – mctuna

+0

@mctuna Кстати, это действительно очень плохая стратегия резервного копирования. Вы должны использовать 'pg_dump' и/или использовать' pg_basebackup' и поточную репликацию или PITR, либо вручную, либо с помощью инструмента, такого как 'pgbarman'. –

+0

Если у вас есть какие-либо предложения или противоречия для следующего случая, я был бы очень доволен. На самом деле наш план состоит в том, чтобы сбрасывать все, кроме таблиц messdaten (столы messdaten огромны, 95% всей базы данных) после этого создают таблицы messdate1234_backup только из данных предыдущего месяца и через редактор sed, редактируя имена файлов и их содержимое messdatenblabla_backup назад к исходным именам (удаление _backup с концов, поэтому, когда мы его вернем, там не будет конфликтов имен) и dump & zip их каждый месяц как name_YYYYMM.ZIP. – mctuna

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) 
+0

спасибо за советы и указав ошибки – mctuna

Смежные вопросы