Экспорт определенных строк из таблицы PostgreSQL как SQL-скрипт INSERT

196

У меня есть схема базы данных с именем: nyummyи таблица с именем cimory:

create table nyummy.cimory (
  id numeric(10,0) not null,
  name character varying(60) not null,
  city character varying(50) not null,
  CONSTRAINT cimory_pkey PRIMARY KEY (id)
);

Я хочу экспортировать cimoryданные таблицы в виде файла сценария вставки SQL. Тем не менее, я хочу экспортировать записи / данные только в том случае, если город равен «Токио» (предположим, что все данные города строчные).

Как это сделать?

Не имеет значения, находится ли решение в бесплатных инструментах с графическим интерфейсом или в командной строке (хотя решение для инструментов с графическим интерфейсом лучше). Я пробовал pgAdmin III, но не могу найти вариант сделать это.

ноль
источник
2
Вы можете пропустить операторы INSERT и просто скопировать, используя SELECT непосредственно между базами данных. albertech.blogspot.com/2016/11/…
баночка
PostgreSQL не может выбирать между базами данных. По крайней мере, старые версии не могут и не могут Greenplum, не знают о 9.x.
PhilHibbs
Я понимаю , что это старый, но я просто хотел бы отметить , что это можно выбрать по базам данных с помощью DBLink , которая была доступна, по крайней мере , V8.3. Он использует сторонние серверы и сторонние оболочки данных для подключения к «удаленным» базам данных. Это работает независимо от того, существуют ли эти базы данных в одном экземпляре или на совершенно разных хостах. Я довольно широко использовал его для создания материализованных представлений в других базах данных, чтобы облегчить определенные отчеты и тому подобное, и это прекрасно работает.
G_Hosa_Phat

Ответы:

282

Создайте таблицу с набором, который вы хотите экспортировать, а затем используйте утилиту командной строки pg_dump для экспорта в файл:

create table export_table as 
select id, name, city
from nyummy.cimory
where city = 'tokyo'
$ pg_dump --table=export_table --data-only --column-inserts my_database > data.sql

--column-inserts сбросит как команды вставки с именами столбцов.

--data-only не сбрасывать схему

Как указано ниже, создание представления вместо таблицы будет исключать создание таблицы всякий раз, когда необходим новый экспорт.

Клодоальдо Нето
источник
3
Хорошо, пока ваше решение работает. Одна вещь, пропущенная, мне нужно добавить "-U user_name". Я также почти преуспел с инструментом ToraSQL, просто он имеет ошибку в данных даты и времени в результате скрипта. Если никто не сможет дать решение по инструменту с графическим интерфейсом в течение 2 дней, ваш ответ будет принят
ноль
2
Просто хотите поделиться с другими людьми, вы также можете использовать этот бесплатный инструмент с графическим интерфейсом: SQL Workbench / J (с драйвером jdbc4 postgreSQL), чтобы сделать то же самое.
ноль
2
Это было бы намного лучше create view export_view..., поскольку представление будет оставаться актуальным с изменениями в базовой таблице. В документах говорят , --table=table: Dump only tables (or **views**...так что я имел некоторую надежду на то, что это будет работать, но демпинг вида , к сожалению , не дает никаких данных. : P
poshes
1
@poshest У меня работает в 9.5. Что именно ты попробовал?
Клодоальдо Нето
@ClodoaldoNeto о, хорошо, отлично! Я надеюсь, что смогу заставить его работать. Я использовал pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sqlверсию 9.5.3, и мое createутверждение было таким же, как ваше, за исключением create view.... Все, что я получаю в выводе, это обычные комментарии и SETзаявления pg_dump . Не уверен, где я иду не так.
21
176

Для экспорта данных только использование COPY.
Вы получаете файл с одной строкой таблицы на строку в виде простого текста (не INSERTкоманд), он меньше и быстрее:

COPY (SELECT * FROM nyummy.cimory WHERE city = 'tokio') TO '/path/to/file.csv';

Импортируйте то же самое в другую таблицу с той же структурой где угодно с:

COPY other_tbl FROM '/path/to/file.csv';

COPYпишет и читает файлы, локальные для сервера , в отличие от клиентских программ, таких как pg_dumpили psqlкоторые читают и записывают файлы, локальные для клиента . Если оба работают на одном компьютере, это не имеет большого значения, но это важно для удаленных подключений.

Существует также \copyкоманда psql, которая:

Выполняет внешнюю (клиентскую) копию. Это операция, которая запускает команду SQL COPY, но вместо чтения или записи указанного файла сервером psql читает или записывает файл и направляет данные между сервером и локальной файловой системой. Это означает, что доступность файлов и привилегии принадлежат локальному пользователю, а не серверу, и никаких привилегий суперпользователя SQL не требуется.

Эрвин Брандштеттер
источник
10
OP вызывает специально для данных как файл сценария вставки SQL . Я думаю, он говорит о insertкомандах, не так ли?
Клодоальдо Нето
1
@Clodoaldo: Вы можете быть правы, в этом случае ваш ответ будет лучше. Можно также скопировать скрипт CREATE в pgAdmin отдельно (так как OP упоминает GUI).
Эрвин Брандштеттер
3
STDINи STDOUTможет использоваться вместо пути к файлу, что полезно для экспорта небольших данных.
Амир Али Акбари
1
Без в --column-insertsфлаге, pg_dump использует COPYиз STDIN для каждой из таблиц в коде SQL он генерирует.
Рэндалл
2
Позаботьтесь о том, чтобы порядок выбранных столбцов соответствовал порядку столбцов в целевой базе данных. Если этого не произойдет, это может привести к сбою или, что еще хуже, к успеху, но вставить неверные данные.
Натан Уоллес
32

Это простой и быстрый способ экспортировать таблицу в скрипт с помощью pgAdmin вручную без дополнительных установок :

  1. Щелкните правой кнопкой мыши на целевой таблице и выберите «Резервное копирование».
  2. Выберите путь к файлу для хранения резервной копии. В качестве формата выберите «Обычный».
  3. Откройте вкладку «Параметры дампа # 2» внизу и установите флажок «Использовать вставки столбцов».
  4. Нажмите кнопку резервного копирования.
  5. Если вы откроете полученный файл с помощью программы чтения текста (например, notepad ++), вы получите скрипт для создания всей таблицы. Оттуда вы можете просто скопировать сгенерированные INSERT-заявления.

Этот метод также работает с техникой создания export_table, как продемонстрировано в ответе @Clodoaldo Neto.

Нажмите справа на целевой таблице и выберите «Резервное копирование»

Выберите путь назначения и измените формат на «Обычный»

Откройте вкладку «Параметры дампа # 2» внизу и установите флажок «Использовать вставки столбцов».

Вы можете скопировать INSERT Заявления оттуда.

Энди Р
источник
Когда я делаю это, у меня нет опции «Bakckup». Это pgAdmin III v1.18.1, подключающийся к Greenplum 4.3.4.1 (на основе PostgreSQL 8.2.15).
PhilHibbs
Я установил pgAdmin III v1.18.1 и там была опция «резервное копирование». Я подключился к PostgreSQL 9.5. Так что проблема, скорее всего, существует между pgAdmin и Greenplum.
Анди Р
Работает как задумано в pgAdmin4
Никхилу
9

SQL Workbench имеет такую ​​функцию.

После выполнения запроса щелкните правой кнопкой мыши результаты запроса и выберите «Копировать данные как SQL> Вставка SQL»

машины
источник
1
Работает отлично. Когда вы выбираете «postgres» в качестве «драйвера», вероятно, вам придется самостоятельно загрузить драйверы JDBC: jdbc.postgresql.org/download.html (это файл .jar - двоичный файл java) и добавить его в качестве «драйвер» соединения postgresql. Строка подключения (или URL как в интерфейсе) должна выглядеть следующим образом: jdbc: postgresql: //127.0.0.1: 5432 / db_name
mrmuggles
DBVisualizer имеет аналогичную и отличную функцию, которая может копировать в файл или прямо в буфер обмена.
Ноумен
8

Для моего варианта использования я смог просто передать данные в grep.

pg_dump -U user_name --data-only --column-inserts -t nyummy.cimory | grep "tokyo" > tokyo.sql
M.Vanderlee
источник
2
Нужно подумать о том, чтобы иметь «Токио» в другой области.
Бюют Джоко Ривай
@BuyutJokoRivai, поскольку в большинстве случаев это дамп только для таблицы, с ним все должно быть в порядке
Исмаил Икбал
Самый умный способ среди других по делу <3
Нам Г.В.У.
Хотя с большой таблицей вы сбросите все строки для grep, что является ловушкой для вашего решения. Затем способ, которым мы запрашиваем и сохраняем результат в таблицу для выгрузки, как здесь: stackoverflow.com/a/12816187/248616 более удобен
Nam G VU
5

Я попытался написать процедуру, которая делает это, основываясь на кодах @PhilHibbs, по-другому. Пожалуйста, посмотрите и проверьте.

 CREATE OR REPLACE FUNCTION dump(IN p_schema text, IN p_table text, IN p_where text)
   RETURNS setof text AS
 $BODY$
 DECLARE
     dumpquery_0 text;
     dumpquery_1 text;
     selquery text;
     selvalue text;
     valrec record;
     colrec record;
 BEGIN

     -- ------ --
     -- GLOBAL --
     --   build base INSERT
     --   build SELECT array[ ... ]
     dumpquery_0 := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table) || '(';
     selquery    := 'SELECT array[';

     <<label0>>
     FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                   FROM information_schema.columns
                   WHERE table_name = p_table and table_schema = p_schema
                   ORDER BY ordinal_position
     LOOP
         dumpquery_0 := dumpquery_0 || quote_ident(colrec.column_name) || ',';
         selquery    := selquery    || 'CAST(' || quote_ident(colrec.column_name) || ' AS TEXT),';
     END LOOP label0;

     dumpquery_0 := substring(dumpquery_0 ,1,length(dumpquery_0)-1) || ')';
     dumpquery_0 := dumpquery_0 || ' VALUES (';
     selquery    := substring(selquery    ,1,length(selquery)-1)    || '] AS MYARRAY';
     selquery    := selquery    || ' FROM ' ||quote_ident(p_schema)||'.'||quote_ident(p_table);
     selquery    := selquery    || ' WHERE '||p_where;
     -- GLOBAL --
     -- ------ --

     -- ----------- --
     -- SELECT LOOP --
     --   execute SELECT built and loop on each row
     <<label1>>
     FOR valrec IN  EXECUTE  selquery
     LOOP
         dumpquery_1 := '';
         IF not found THEN
             EXIT ;
         END IF;

         -- ----------- --
         -- LOOP ARRAY (EACH FIELDS) --
         <<label2>>
         FOREACH selvalue in ARRAY valrec.MYARRAY
         LOOP
             IF selvalue IS NULL
             THEN selvalue := 'NULL';
             ELSE selvalue := quote_literal(selvalue);
             END IF;
             dumpquery_1 := dumpquery_1 || selvalue || ',';
         END LOOP label2;
         dumpquery_1 := substring(dumpquery_1 ,1,length(dumpquery_1)-1) || ');';
         -- LOOP ARRAY (EACH FIELD) --
         -- ----------- --

         -- debug: RETURN NEXT dumpquery_0 || dumpquery_1 || ' --' || selquery;
         -- debug: RETURN NEXT selquery;
         RETURN NEXT dumpquery_0 || dumpquery_1;

     END LOOP label1 ;
     -- SELECT LOOP --
     -- ----------- --

 RETURN ;
 END
 $BODY$
   LANGUAGE plpgsql VOLATILE;

А потом :

-- for a range
SELECT dump('public', 'my_table','my_id between 123456 and 123459'); 
-- for the entire table
SELECT dump('public', 'my_table','true');

протестировано на моем postgres 9.1, с таблицей со смешанным типом данных поля (text, double, int, отметка времени без часового пояса и т. д.)

Вот почему необходим CAST в текстовом виде. Мой тестовый запуск правильно для примерно 9 миллионов строк, похоже, что он провалился за 18 минут.

PS: я нашел эквивалент для MySQL на веб-сайте.

Ви Шен
источник
3

Вы можете просмотреть таблицу с указанными записями, а затем сбросить файл sql.

CREATE VIEW foo AS
SELECT id,name,city FROM nyummy.cimory WHERE city = 'tokyo'
Георгий Пейкришвили
источник
3
Я пробовал это в pgAdmin III, но для объекта View нет никакой опции для дампа.
нуль
Попробуй навикать. Я использую его, и у него есть опция экспорта сценария sql
Giorgi Peikrishvili
@Giorgi: есть бесплатная версия?
ноль
Невозможно использовать Postgres 9.1
HCarrasko
2

Я просто выполнил быструю процедуру, чтобы сделать это. Это работает только для одной строки, поэтому я создаю временное представление, которое просто выбирает нужную строку, а затем заменяю pg_temp.temp_view на фактическую таблицу, в которую я хочу вставить.

CREATE OR REPLACE FUNCTION dv_util.gen_insert_statement(IN p_schema text, IN p_table text)
  RETURNS text AS
$BODY$
DECLARE
    selquery text; 
    valquery text; 
    selvalue text; 
    colvalue text; 
    colrec record;
BEGIN

    selquery := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table);

    selquery := selquery || '(';

    valquery := ' VALUES (';
    FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                  FROM information_schema.columns 
                  WHERE table_name = p_table and table_schema = p_schema 
                  ORDER BY ordinal_position 
    LOOP
      selquery := selquery || quote_ident(colrec.column_name) || ',';

      selvalue := 
        'SELECT CASE WHEN ' || quote_ident(colrec.column_name) || ' IS NULL' || 
                   ' THEN ''NULL''' || 
                   ' ELSE '''' || quote_literal('|| quote_ident(colrec.column_name) || ')::text || ''''' || 
                   ' END' || 
        ' FROM '||quote_ident(p_schema)||'.'||quote_ident(p_table);
      EXECUTE selvalue INTO colvalue;
      valquery := valquery || colvalue || ',';
    END LOOP;
    -- Replace the last , with a )
    selquery := substring(selquery,1,length(selquery)-1) || ')';
    valquery := substring(valquery,1,length(valquery)-1) || ')';

    selquery := selquery || valquery;

RETURN selquery;
END
$BODY$
  LANGUAGE plpgsql VOLATILE;

Вызывается так:

SELECT distinct dv_util.gen_insert_statement('pg_temp_' || sess_id::text,'my_data') 
from pg_stat_activity 
where procpid = pg_backend_pid()

Я не проверял это против атак с использованием инъекций, пожалуйста, дайте мне знать, если для этого недостаточно вызова quote_literal.

Также это работает только для столбцов, которые можно просто привести к :: text и обратно.

Также это для Greenplum, но я не могу придумать причину, по которой он не будет работать на Postgres, CMIIW.

PhilHibbs
источник
-2

вы пробовали в pgadmin выполнить запрос с " EXECUTE QUERY WRITE RESULT TO FILE " опцией

его только экспорт данных, иначе попробуйте как

pg_dump -t view_name DB_name > db.sql

Опция -t используется для ==> дампить только таблицы (или представления или последовательности), соответствующие таблице, см.

solaimuruganv
источник
1
Это только экспортирует create viewзаявление
cdmckay