Експортуйте конкретні рядки з таблиці PostgreSQL як сценарій INSERT SQL


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. Однак я хочу експортувати записи / дані лише там, де місто дорівнює 'tokyo' (припустимо, що дані про місто - це малі регістри).

Як це зробити?

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


2
ви можете пропустити оператори INSERT і просто скопіювати за допомогою SELECT безпосередньо між базами даних. albertech.blogspot.com/2016/11/…
jar

PostgreSQL не може вибирати в різних базах даних. Принаймні, старіші версії не можуть і не можуть Greenplum, не знаю про 9.x.
PhilHibbs

Я розумію , що це старий, але я просто хотів би відзначити , що це можна вибрати по базах даних з допомогою DBLink , яка була доступна, по крайней мере , V8.3. Для підключення до "віддалених" баз даних використовуються іноземні сервери та іноземні обгортки даних. Це працює, чи існують ці бази даних в одному і тому ж екземплярі або зовсім інші хости. Я досить широко використовував це для створення матеріалізованих поглядів в інші бази даних для полегшення певної звітності, і таке, і це чудово працює.
G_Hosa_Phat

Відповіді:


280

Створіть таблицю з набором, який потрібно експортувати, а потім скористайтеся утилітою командного рядка 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, це просто те, що він має помилку в датах часу даних в результаті скрипту. Якщо ніхто не може дати рішення інструменту GUI через 2 дні, ваша відповідь буде прийнята
нульове

2
Просто хочете поділитися з іншими людьми, ви можете також скористатися цим безкоштовним інструментом GUI: SQL Workbench / J (з postgreSQL jdbc4 драйвером), щоб зробити те саме.
null

1
Це було б набагато краще create view export_view..., оскільки подання залишатиметься в курсі змін до базової таблиці. У документах кажуть , --table=table: Dump only tables (or **views**...так що я мав деяку надію на те, що це буде працювати, але демпінг виду , до жаль , не дає ніяких даних. : P
найвище

@poshest Це працює для мене в 9.5. Що саме ви спробували?
Clodoaldo Neto

@ClodoaldoNeto о, гаразд чудово! Я сподіваюся, що я також можу працювати. Я використовував pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sql, версію 9.5.3, і моя createзаява була такою ж, як і ваша, за винятком create view.... Все, що я отримую у результаті, - це звичайні коментарі та SETзаяви pg_dump . Не впевнений, де я помиляюся.
Останні

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, що:

Виконує передню (клієнтську) копію. Це операція, яка виконує COPYкоманду SQL , але замість того, щоб сервер читав або записував вказаний файл, psql зчитує або записує файл і спрямовує дані між сервером і локальною файловою системою. Це означає, що доступність файлів і привілеї - це місцевий користувач, а не сервер, і ніякі привілеї суперпользователя SQL не потрібні.


10
ОП закликає спеціально для даних, як вставити файл скрипту sql . Я думаю, він говорить про insertкоманди, чи не так?
Clodoaldo Neto

1
@Clodoaldo: Ви, можливо, маєте рацію, і в цьому випадку ваша відповідь буде краще відповідати. Можна також окремо скопіювати CREATE-скрипт у pgAdmin (як в ОП згадуються графічні інтерфейси).
Ервін Брандстеттер

3
STDINі STDOUTможе використовуватися замість шляху файлів, корисного для невеликого експорту даних.
Амір Алі Акбарі

1
Без в --column-insertsпрапорі, pg_dump використовує COPYз STDIN для кожної з таблиць в коді SQL він генерує.
Рандалл

2
Слідкуйте за тим, щоб порядок стовпців, які ви вибираєте, відповідав порядку розташування стовпців у базі даних призначення. Якщо цього не зробити, це може не вдатися, або ще гірше, але вдасться вставити погані дані.
Натан Уоллес

32

Це простий і швидкий спосіб експорту таблиці в скрипт з pgAdmin вручну без додаткових установок :

  1. Клацніть правою кнопкою миші на цільовій таблиці та виберіть "Резервне копіювання".
  2. Виберіть шлях до файлу для зберігання резервної копії. Як формат виберіть "Звичайний".
  3. Відкрийте вкладку "Параметри скидання №2" внизу і поставте галочку "Використовувати вставки стовпців".
  4. Натисніть кнопку Резервне копіювання.
  5. Якщо ви відкриєте отриманий файл за допомогою текстового зчитувача (наприклад, блокнот ++), ви отримаєте сценарій для створення всієї таблиці. Звідти ви можете просто скопіювати створені INSERT-заяви.

Цей метод також працює з технікою створення Export_table, як показано у відповіді @Clodoaldo Neto.

Клацніть праворуч на цільовій таблиці та виберіть "Резервне копіювання"

Виберіть шлях призначення та змініть формат на "Звичайний"

Відкрийте вкладку "Параметри скидання №2" внизу та встановіть прапорець "Використовувати вставки стовпців"

Ви можете скопіювати Звідки про ВСТУП.


Коли я це роблю, немає варіанту "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.
Andi R

Працює за призначенням у pgAdmin4
Nikhil

9

SQL Workbench має таку особливість.

Після запуску запиту клацніть правою кнопкою миші результати пошуку та виберіть "Скопіювати дані як SQL> Вставка SQL"


1
Це чудово працює. Коли ви вибираєте "postgres" як "драйвер", можливо, вам доведеться самостійно завантажити драйвери JDBC: jdbc.postgresql.org/download.html (це файл .jar - java binary) і додати його як 'драйвер' з'єднання postgresql. Рядок підключення (або URL-адреса як в інтерфейсі) повинен виглядати так: jdbc: postgresql: //127.0.0.1: 5432 / db_name
mrmuggles

DBVisualizer має подібну та чудову функцію, яка може скопіювати у файл або прямо у буфер обміну.
Номенон

8

У моєму випадку я міг просто подати на греп.

pg_dump -U user_name --data-only --column-inserts -t nyummy.cimory | grep "tokyo" > tokyo.sql

2
Потрібно подумати про те, щоб мати «токіо» в іншій галузі.
Буют Джоко Рівай

@BuyutJokoRivai, оскільки це лише таблиця, демпф у більшості випадків має бути добре
Ісмаїл Ікбал

Найрозумніший спосіб серед інших у справі <3
Nam G VU

Хоча з великим столом, ви скинете всі рядки для грепу, що є справжньою справою для вашого рішення. Тоді, як ми запиту і зберегти результат в таблиці звалювати , як тут stackoverflow.com/a/12816187/248616 більш suiteable
Нам 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');

перевірено на моїх постгресах 9.1 із таблицею зі змішаним типом даних поля (текст, подвійний, int, часова мітка без часового поясу тощо).

Ось чому потрібна форма CAST у форматі TEXT. Мій тестовий пробіг вірно близько 9М ліній, схоже, він вийшов з ладу лише за 18 хвилин бігу.

ps: Я знайшов еквівалент mysql в WEB.


3

Ви можете зробити перегляд таблиці зі специфічними записами, а потім скинути файл sql

CREATE VIEW foo AS
SELECT id,name,city FROM nyummy.cimory WHERE city = 'tokyo'

3
Я спробував це в pgAdmin III, але для об’єкта View немає можливості демпінгу.
null

Спробуйте navicat. Я використовую його, і він має опцію скрипту для експорту sql
Giorgi Peikrishvili

@Giorgi: чи існує безкоштовна версія?
null

Неможливо використовувати 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()

Я не перевіряв це на нападів ін'єкцій, повідомте мене, якщо виклик quo_literal для цього недостатній

Крім того, він працює лише для стовпців, які можна просто передати :: текст і повернути знову.

Також це стосується Greenplum, але я не можу придумати причину, чому він не працював би на Postgres, CMIIW.


-2

Ви спробували у виконанні запиту з pgadmin " EXECUTE QUERY WRITE RESULT TO FILE " опцією

єдиний експорт даних, спробуйте, як

pg_dump -t view_name DB_name > db.sql

-t варіант, що використовується для ==> Дамп лише таблиць (або представлень або послідовностей) таблиці, що відповідає, див


1
Це експортує лише create viewзаяву
cdmckay
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.