Създаване на таблица с PSQL като клонинг на друга таблица, но без колона

Кратка версия: Коя psql команда трябва да използвам, за да създам временна таблица, която е клонинг на дадена таблица, с изключение на дадена колона?

create temp table bar_temp as <columns from foo.bar excluding 'insert_date'>

Обосновка: Имам някои много големи CSV файлове, които искам да кача групово в Postges DB (понастоящем 8.4 - мигрирам към 9.x).

Когато качвам тези CSV файлове, искам да добавя допълнително поле, например поле "дата".

Използване на тази публикация като вдъхновение: (Как да актуализирам избрани редове със стойности от CSV файл в Postgres?) Опитвам се да направя следното:

  1. Създайте временна таблица от схемата на целевата таблица, като изключите колоната "дата".
  2. Изпълнете командата '\COPY', за да качите във временната таблица.
  3. Актуализирайте записите в целевата таблица със записите във временната таблица + допълнителния запис в колоната за дата.

Всичко това е ясно, с изключение на стъпка 1. Ако имената на колоните са известни предварително, този ред може да бъде твърдо кодиран. В моя случай имам редица подобни входни файлове със съответните таблици и искам решението да бъде гъвкаво, за да се справи с промените в схемата.

Моето хакерско решение е да имам скрипт за предварителна обработка, който определя схемата на временната таблица, след което записва тази команда CREATE в SQL скрипта, преди да се изпълни, напр.

"SELECT 'SELECT ' || array_to_string(ARRAY(SELECT 'o' || '.' || c.column_name FROM information_schema.columns As c WHERE table_name = '$table' AND c.column_name NOT IN('dt')), ',') || ' FROM $schema.$table As o'"

което ми дава нещо подобно

SELECT o.name,o.address from foo.bar As o

който след това може да се използва в оператора create

create temp table temp_tbl as SELECT o.name,o.address from foo.bar As o

Мисля обаче, че трябва да се избягва извършването на тази стъпка за откриване на схема в самия PSQL скрипт. Разгледах използването на "EXEC", но доколкото както виждам, ще трябва да поставя това във функция, типът връщане на това трябва да изброява колоните на таблицата!

Някакви предположения?


person Jim    schedule 24.05.2013    source източник
comment
Можете да направите това с PL/PgSQL, като използвате EXECUTE, обикновено с FORMAT. Направете заявка към information_schema или pg_catalog изгледи, за да получите списъка с колони на таблицата. Ще оставя подробен пример на някой друг, но това трябва да ви насочи на правилния път. В SQL няма концепция за казване Всички колони освен тази.   -  person Craig Ringer    schedule 24.05.2013


Отговори (2)


Бихте могли да направите нещо подобно:

create table foo like bar;
alter table foo drop column baz;
-- and now full the thing
person Denis de Bernardy    schedule 24.05.2013
comment
Ах! разбира се. Трябваше да използвам create temp table temp_tbl като select * from src_table where false с моята версия. - person Jim; 24.05.2013

Благодарение на идеята на Денис в правилната посока, ето моя шаблонен скрипт:

create temp table $tempTable as SELECT * from $schema.$table where false;
alter table $tempTable drop column $dateColumn;
\\COPY $tempTable FROM '$file' CSV HEADER
DELETE from $schema.$table where $dateColumn='$dt'::date;\
INSERT into $schema.$table select '$dt'::date, * from $tempTable;
DROP TABLE $tempTable;

Въпреки че все още ми е интересно да разбера как можах да накарам EXECUTE да работи..

person Jim    schedule 28.05.2013