Привет, Я DocuDroid!
Оценка ИИ поиска
Спасибо за оценку нашего ИИ поиска!
Мы будем признательны, если вы поделитесь своими впечатлениями, чтобы мы могли улучшить наш ИИ поиск для вас и других читателей.
GitHub

Команда COPY

Антон Монаков

Команда COPY используется для копирования данных между таблицами Greengage DB и обычными файлами в файловой системе, а также через ввод / вывод программы или стандартные потоки. Команду можно использовать только с обычными таблицами, пишущими внешними таблицами или результатом выполнения запроса SELECT, но не с читающими внешними таблицами или представлениями.

Если не указано выражение ON SEGMENT, команда COPY исполняется не параллельно (данные загружаются в одном процессе, используя мастер-сегмент Greengage DB), поэтому рекомендуется использовать ее только для небольших файлов.

Для использования COPY TO необходима привилегия SELECT на таблицу, из которой будет осуществляться чтение данных, а для использования COPY FROM — привилегия INSERT на таблицу, в которую будет осуществляться запись. Достаточно выдать привилегии на столбцы таблиц, перечисленные в команде. Более подробную информацию об управлении доступом в Greengage DB можно получить в статье Роли и привилегии.

Пользователю, не являющемуся суперпользователем, доступны только команды COPY FROM STDIN и COPY TO STDOUT. Более подробную информацию можно получить в разделе Загрузка данных через стандартные потоки ввода / вывода.

Обзор синтаксиса

Синтаксис команды COPY приведен ниже. Полное описание выражений и параметров в разделе Описание выражений и параметров.

COPY [BINARY] <table_name> [(<column_name> [, ...])]
FROM {'<filename>' | PROGRAM '<command>' | STDIN}
[ ON SEGMENT ]
[IGNORE EXTERNAL PARTITIONS]
[[LOG ERRORS]
SEGMENT REJECT LIMIT <count> [ ROWS | PERCENT ]]
[ [ WITH ] (
    FORMAT <'text' | 'csv' | 'binary'>,
    OIDS [ <boolean> ],
    FREEZE [ <boolean> ],
    DELIMITER '<delimiter_character>',
    NULL '<null string>',
    HEADER [ <boolean> ],
    QUOTE '<quote_character>',
    NEWLINE '<newline_character>',
    ESCAPE '<escape_character>',
    FORCE_QUOTE { ( <column_name> [, ...] ) | * },
    FORCE_NOT_NULL ( <column_name> [, ...] ),
    FORCE_NULL ( <column_name> [, ...] ),
    ENCODING '<encoding_name>',
    FILL MISSING FIELDS
    ) ]
COPY [BINARY] { <table_name> [(<column_name> [, ...])] | (<query>)}
TO {'<filename>' | PROGRAM '<command>' | STDOUT}
[ ON SEGMENT ]
[IGNORE EXTERNAL PARTITIONS]
[[LOG ERRORS]
SEGMENT REJECT LIMIT <count> [ ROWS | PERCENT ]]
[ [ WITH ] (
    FORMAT <'text' | 'csv' | 'binary'>,
    OIDS [ <boolean> ],
    FREEZE [ <boolean> ],
    DELIMITER '<delimiter_character>',
    NULL '<null string>',
    HEADER [ <boolean> ],
    QUOTE '<quote_character>',
    NEWLINE '<newline_character>',
    ESCAPE '<escape_character>',
    FORCE_QUOTE { ( <column_name> [, ...] ) | * },
    FORCE_NOT_NULL ( <column_name> [, ...] ),
    FORCE_NULL ( <column_name> [, ...] ),
    ENCODING '<encoding_name>',
    FILL MISSING FIELDS
    ) ]
ПРИМЕЧАНИЕ

При перечислении опций внутри выражения WITH требуется заменять пробелы в их именах символом нижнего подчеркивания (_), например, FILL_MISSING_FIELDS, ON_SEGMENT. Вы также можете опустить выражение WITH, указав каждую опцию отдельно.

В нижеприведенном примере демонстрируются две эквивалентные команды:

  • С использованием WITH:

    COPY customers FROM '/tmp/customers_<SEGID>.csv'
    WITH (
        FORMAT CSV,
        HEADER,
        ON_SEGMENT
    );
  • Без использования WITH:

    COPY customers FROM '/tmp/customers_<SEGID>.csv'
    CSV
    HEADER
    ON SEGMENT;

Примеры использования

Предварительные требования

Для выполнения примеров из этого раздела подключитесь к мастер-хосту Greengage DB как gpadmin с помощью psql, как описано в статье Подключение к Greengage DB с использованием psql. Затем создайте тестовую базу данных customers и подключитесь к ней:

DROP DATABASE IF EXISTS customers;
CREATE DATABASE customers;
\c customers

Затем создайте таблицу customers:

CREATE TABLE customers
(
    id INTEGER,
    first_name VARCHAR(50),
    last_name VARCHAR(50),
    email VARCHAR(100),
    address VARCHAR(255)
)
    DISTRIBUTED RANDOMLY;

Загрузка данных из файлов / в файлы

Для того чтобы напрямую считать данные из файла, расположенного на мастер-хосте Greengage DB, или записать данные в файл, запустите команду COPY, передав в опции <filename> путь к файлу. COPY FROM служит для копирования данных из файла в таблицу, добавляя их к уже имеющимся в таблице данным. COPY TO позволяет скопировать данные таблицы в файл (или в несколько файлов согласно ID сегмента, как описано в разделе Использование выражения ON SEGMENT).

COPY [BINARY] <table_name> [(<column_name> [, ...])]
FROM '<filename>'
[ ON SEGMENT ]
[ [ WITH ] ( <option> [, ...] ) ]
COPY [BINARY] { <table_name> [(<column_name> [, ...])] | (<query>)}
TO '<filename>'
[ ON SEGMENT ]
[ [ WITH ] ( <option> [, ...] ) ]

Если не используется выражение ON SEGMENT, в качестве пути должен быть указан абсолютный путь на мастер-хосте Greengage DB или путь относительно каталога данных мастера. Если выражение ON SEGMENT используется, в качестве пути должен быть указан путь на сегмент-хосте Greengage DB. Файлы должны быть доступны на чтение и запись суперпользователю Greengage DB (или пользователю, от имени которого запущен сервер), а не клиенту. Чтение и запись файлов напрямую с помощью команды COPY доступно только суперпользователям, так как позволяет обращаться к любым файлам, доступным серверу.

ПРИМЕЧАНИЕ

В операционных системах семейства Windows следует использовать спецпоследовательности, начинающиеся с E'', и двойные символы обратной косой черты в пути файла.

Примеры

В данных примерах команда COPY используется для копирования содержимого файла customers.csv в таблицу БД customers, а содержимого таблицы БД — в файл.

  1. В каталоге /tmp мастер-хоста создайте файл customers.csv:

    id,first_name,last_name,email,address
    1,John,Doe,john.doe@example.com,123 Elm Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street
  2. Очистите таблицу customers:

    TRUNCATE TABLE customers;
  3. Выполните команду COPY FROM. В выражении WITH укажите CSV в качестве формата данных и включите пропуск заголовка (HEADER):

    COPY customers FROM '/tmp/customers.csv'
    WITH (FORMAT CSV, HEADER);
  4. Выполните запрос к таблице customers:

    TABLE customers;

    Вывод должен выглядеть следующим образом:

     id | first_name | last_name |         email          |      address
    ----+------------+-----------+------------------------+-------------------
      1 | John       | Doe       | john.doe@example.com   | 123 Elm Street
      2 | Jane       | Smith     | jane.smith@example.com | 456 Oak Street
      3 | Bob        | Brown     | bob.brown@example.com  | 789 Pine Street
      4 | Rob        | Stuart    | rob.stuart@example.com | 119 Willow Street
  1. Очистите таблицу customers и заполните ее данными:

    TRUNCATE TABLE customers;
    
    INSERT INTO customers (id, first_name, last_name, email, address)
    VALUES (1,'John','Doe','john.doe@example.com','123 Elm Street'),
           (2,'Jane','Smith','jane.smith@example.com','456 Oak Street'),
           (3,'Bob','Brown','bob.brown@example.com','789 Pine Street'),
           (4,'Rob','Stuart','rob.stuart@example.com','119 Willow Street');
  2. Выполните команду COPY TO. В выражении WITH укажите CSV в качестве формата данных и включите добавление заголовка (HEADER):

    COPY customers TO '/tmp/customers.csv'
    WITH (FORMAT CSV, HEADER);
  3. Проверьте содержимое файла customers.csv, созданного в каталоге /tmp:

    $ cat /tmp/customers.csv

    Вывод должен выглядеть следующим образом:

    id,first_name,last_name,email,address
    1,John,Doe,john.doe@example.com,123 Elm Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street

Загрузка данных с помощью программы

Для загрузки данных (или их выгрузки) в таблицу БД с помощью программы запустите команду COPY, передав в выражении PROGRAM команду (<command>):

COPY [BINARY] <table_name> [(<column_name> [, ...])]
FROM PROGRAM '<command>'
[ ON SEGMENT ]
[ [ WITH ] ( <option> [, ...] ) ]
COPY [BINARY] { <table_name> [(<column_name> [, ...])] | (<query>)}
TO PROGRAM '<command>'
[ ON SEGMENT ]
[ [ WITH ] ( <option> [, ...] ) ]

Команда должна быть указана так, как если бы она была непосредственно введена на мастер-хосте Greengage DB (если не используется выражение ON SEGMENT), и должна быть исполняемой суперпользователем. При использовании COPY FROM осуществляется чтение из стандартного вывода команды. При использовании COPY TO осуществляется запись в стандартный ввод команды.

Если указано выражение ON SEGMENT, команда должна быть доступна для исполнения суперпользователю Greengage DB на всех сегмент-хостах, а в теле команды должна использоваться подстрока <SEGID>, все вхождения которой будут заменены на идентификатор контента текущего сегмента.

ПРИМЕЧАНИЕ

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

Примеры

В данных примерах команда COPY используется для чтения и записи файла customers.csv с помощью утилиты cat.

  1. В каталоге /tmp мастер-хоста создайте файл customers.csv:

    id,first_name,last_name,email,address
    1,John,Doe,john.doe@example.com,123 Elm Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street
  2. Очистите таблицу customers:

    TRUNCATE TABLE customers;
  3. Выполните команду COPY FROM. В выражении PROGRAM укажите команду cat. В выражении WITH укажите CSV в качестве формата данных и включите пропуск заголовка (HEADER):

    COPY customers FROM PROGRAM 'cat /tmp/customers.csv'
    WITH (FORMAT CSV, HEADER);
  4. Выполните запрос к таблице customers:

    TABLE customers;

    Вывод должен выглядеть следующим образом:

     id | first_name | last_name |         email          |      address
    ----+------------+-----------+------------------------+-------------------
      1 | John       | Doe       | john.doe@example.com   | 123 Elm Street
      2 | Jane       | Smith     | jane.smith@example.com | 456 Oak Street
      3 | Bob        | Brown     | bob.brown@example.com  | 789 Pine Street
      4 | Rob        | Stuart    | rob.stuart@example.com | 119 Willow Street
  1. Очистите таблицу customers и заполните ее данными:

    TRUNCATE TABLE customers;
    
    INSERT INTO customers (id, first_name, last_name, email, address)
    VALUES (1,'John','Doe','john.doe@example.com','123 Elm Street'),
           (2,'Jane','Smith','jane.smith@example.com','456 Oak Street'),
           (3,'Bob','Brown','bob.brown@example.com','789 Pine Street'),
           (4,'Rob','Stuart','rob.stuart@example.com','119 Willow Street');
  2. Выполните команду COPY TO. В выражении WITH укажите CSV в качестве формата данных и включите добавление заголовка (HEADER):

    COPY customers TO PROGRAM 'cat > /tmp/customers.csv'
    WITH (FORMAT CSV, HEADER);
  3. Проверьте содержимое файла customers.csv, созданного в каталоге /tmp:

    $ cat /tmp/customers.csv

    Вывод должен выглядеть следующим образом:

    id,first_name,last_name,email,address
    1,John,Doe,john.doe@example.com,123 Elm Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street

Загрузка данных через стандартные потоки ввода / вывода

Для чтения или записи данных таблицы БД через стандартный ввод (stdin) или стандартный вывод (stdout) запустите команду COPY, указав выражение STDIN или STDOUT:

COPY [BINARY] <table_name> [(<column_name> [, ...])]
FROM STDIN
[ [ WITH ] ( <option> [, ...] ) ]
COPY [BINARY] { <table_name> [(<column_name> [, ...])] | (<query>)}
TO STDOUT
[ [ WITH ] ( <option> [, ...] ) ]

STDIN указывает, что на вход поступают данные от клиентского приложения. STDOUT указывает, что вывод направляется в клиентское приложение. Данные передаются через соединение между клиентом и мастером. Использование выражения ON SEGMENT совместно с STDIN и STDOUT не поддерживается.

РЕКОМЕНДАЦИЯ

Чтобы иметь возможность передавать данные на вход и вывод из COPY с помощью конвейера (|), выполните ее как часть команды psql непосредственно из командной строки, как описано в разделе Выполнение команд в неинтерактивном режиме. Используйте опцию -d для указания базы данных для подключения (<database>) и опцию -c для указания выполняемой команды, например:

$ psql -d <database> -c 'COPY <table_name> FROM STDIN WITH (FORMAT CSV)'

Для выполнения загрузки / выгрузки данных на стороне клиента (client copy) воспользуйтесь метакомандой \copy, как описано в разделе Загрузка данных с помощью \copy.

Примеры

В данных примерах команда COPY используется для записи пользовательских данных в таблицу customers через стандартный ввод (stdin) и вывода содержимого таблицы через стандартный вывод (stdout). Ввод и вывод данных осуществляется с помощью клиентского терминала.

  1. Очистите таблицу customers:

    TRUNCATE TABLE customers;
  2. Выполните команду COPY FROM. В выражении WITH укажите CSV в качестве формата данных.

    COPY customers FROM STDIN
    WITH (FORMAT CSV);
  3. Greengage DB отобразит интерактивный запрос ввода. Введите желаемые значения, разделенные запятой. Начинайте каждую строку данных с новой строки и завершите ввод, набрав \. на отдельной строке:

    1,John,Doe,john.doe@example.com,123 Elm Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street
    \.
  4. Выполните запрос к таблице customers:

    TABLE customers;

    Вывод должен выглядеть следующим образом:

     id | first_name | last_name |         email          |      address
    ----+------------+-----------+------------------------+-------------------
      1 | John       | Doe       | john.doe@example.com   | 123 Elm Street
      2 | Jane       | Smith     | jane.smith@example.com | 456 Oak Street
      3 | Bob        | Brown     | bob.brown@example.com  | 789 Pine Street
      4 | Rob        | Stuart    | rob.stuart@example.com | 119 Willow Street
  1. Очистите таблицу customers и заполните ее данными:

    TRUNCATE TABLE customers;
    
    INSERT INTO customers (id, first_name, last_name, email, address)
    VALUES (1,'John','Doe','john.doe@example.com','123 Elm Street'),
           (2,'Jane','Smith','jane.smith@example.com','456 Oak Street'),
           (3,'Bob','Brown','bob.brown@example.com','789 Pine Street'),
           (4,'Rob','Stuart','rob.stuart@example.com','119 Willow Street');
  2. Выполните команду COPY TO. В выражении WITH укажите CSV в качестве формата данных и включите добавление заголовка (HEADER):

    COPY customers TO STDOUT
    WITH (FORMAT CSV, HEADER);

    Вывод должен выглядеть следующим образом:

    id,first_name,last_name,email,address
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    1,John,Doe,john.doe@example.com,123 Elm Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street

Загрузка данных с помощью \copy

Для выполнения загрузки / выгрузки данных на стороне клиента (client copy) воспользуйтесь метакомандой \copy.

\copy выполняет команду COPY FROM STDIN / COPY TO STDOUT, а затем загружает или выгружает данные в файл, доступный на стороне клиентской утилиты psql.

Чтение и запись данных осуществляются не сервером БД, а утилитой psql, которая перемещает данные между сервером и локальной файловой системой. Следовательно, файл должен находиться на хосте, где работает клиент psql, и быть доступен пользователю, от имени которого запущена утилита.

ВНИМАНИЕ

Команда \copy доступна только при подключении к Greengage DB с помощью psql, как описано в статье Подключение к Greengage DB с использованием psql. При использовании других клиентских приложений команда \copy недоступна.

Синтаксис команды \copy похож на синтаксис COPY:

\copy { table [ ( <column_list> ) ] | ( <query> ) }
{ from | to }
{ 'filename' | program 'command' | stdin | stdout | pstdin | pstdout }
[ [ with ] ( <option> [, ...] ) ]

При использовании \copy from stdin бэкенд принимает данные, пока не будет введена строка, содержащая только сочетание обратной косой черты и точки (\.), или поток не достигнет индикатора окончания данных (EOF). При использовании \copy to stdout вывод направляется туда же, куда и стандартный вывод psql. Для чтения и записи данных через стандартные потоки ввода / вывода psql вне зависимости от текущих входов и выходов команды или указанных опций -f или -o используйте from pstdin или to pstdout.

Использование выражения ON SEGMENT совместно с \copy не поддерживается.

Примеры

В данных примерах команда \copy используется для копирования содержимого файла customers.csv в таблицу БД customers, а содержимого таблицы БД — в файл.

  1. В каталоге /tmp мастер-хоста создайте файл customers.csv:

    id,first_name,last_name,email,address
    1,John,Doe,john.doe@example.com,123 Elm Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street
  2. Очистите таблицу customers:

    TRUNCATE TABLE customers;
  3. Выполните команду \copy from. В выражении with укажите csv в качестве формата данных и включите пропуск заголовка (header):

    \copy customers from '/tmp/customers.csv' with (format csv,header)
  4. Выполните запрос к таблице customers:

    TABLE customers;

    Вывод должен выглядеть следующим образом:

     id | first_name | last_name |         email          |      address
    ----+------------+-----------+------------------------+-------------------
      1 | John       | Doe       | john.doe@example.com   | 123 Elm Street
      2 | Jane       | Smith     | jane.smith@example.com | 456 Oak Street
      3 | Bob        | Brown     | bob.brown@example.com  | 789 Pine Street
      4 | Rob        | Stuart    | rob.stuart@example.com | 119 Willow Street
  1. Очистите таблицу customers и заполните ее данными:

    TRUNCATE TABLE customers;
    
    INSERT INTO customers (id, first_name, last_name, email, address)
    VALUES (1,'John','Doe','john.doe@example.com','123 Elm Street'),
           (2,'Jane','Smith','jane.smith@example.com','456 Oak Street'),
           (3,'Bob','Brown','bob.brown@example.com','789 Pine Street'),
           (4,'Rob','Stuart','rob.stuart@example.com','119 Willow Street');
  2. Выполните команду \copy to. В выражении with укажите csv в качестве формата данных и включите добавление заголовка (header):

    \copy customers to '/tmp/customers.csv' with (format csv,header)
  3. Проверьте содержимое файла customers.csv, созданного в каталоге /tmp:

    $ cat /tmp/customers.csv

    Вывод должен выглядеть следующим образом:

    id,first_name,last_name,email,address
    1,John,Doe,john.doe@example.com,123 Elm Street
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street

Использование выражения ON SEGMENT

С помощью выражения ON SEGMENT команды COPY можно указать отдельные файлы данных каждого сегмента, расположенные на сегмент-хостах. В каждом таком файле содержатся данные таблицы, которые обрабатывает сегмент. Например, при копировании данных таблицы в файл с помощью команды COPY TO …​ ON SEGMENT на каждом сегмент-хосте создается по файлу на каждый сегмент. В отличие от стандартной операции COPY, файлы создаются на сегмент-хостах, а не на мастер-хосте. Команда не копирует данные с зеркал или на зеркала сегментов и не создает файлов на зеркалах.

Выражение ON SEGMENT можно использовать для переноса данных между кластерами или выполнения резервного копирования. Сегментированные данные можно восстановить, например, с помощью утилиты gpfdist, применяемой для высокоскоростной загрузки данных.

Синтаксис команды COPY …​ ON SEGMENT в общем виде выглядит следующим образом:

COPY [BINARY] <table_name> [(<column_name> [, ...])]
FROM {'<filename>' | PROGRAM '<command>'}
[ ON SEGMENT ]
[ [ WITH ] ( <option> [, ...] ) ]
COPY [BINARY] { <table_name> [(<column_name> [, ...])] | (<query>)}
TO {'<filename>' | PROGRAM '<command>'}
[ ON SEGMENT ]
[ [ WITH ] ( <option> [, ...] ) ]
ПРИМЕЧАНИЕ

Использование выражения ON SEGMENT совместно с STDIN и STDOUT не поддерживается.

При указании абсолютного пути к файлу как напрямую (<filename>), так и внутри команды (<command>) используйте строковые литералы <SEG_DATA_DIR> и <SEGID> следующим образом:

COPY <table>
[TO|FROM] '<SEG_DATA_DIR>/<datafilename><SEGID>_<suffix>'
ON SEGMENT;

где:

  • <SEG_DATA_DIR> — абсолютный путь к каталогу данных сегмента. Использование литерала опционально: вместо него можно указать абсолютный путь.

  • <SEGID> — идентификатор контента текущего сегмента. Литерал <SEGID> обязателен, если используется выражение ON SEGMENT. В выражении COPY FROM идентификатор контента текущего сегмента следует указывать в имени исходного файла, расположенного на соответствующем сегменте. На каждом сегменте каждого сегмент-хоста должен существовать файл с данными.

При запуске команды COPY вместо литералов подставляются соответствующие значения идентификаторов контента и путей каталога данных.

ПРИМЕЧАНИЕ

Угловые скобки (< и >) — это часть строкового литерала.

При выполнении команды COPY FROM …​ ON SEGMENT и копировании данных в таблицу проверяется тип распределения данных таблицы. Если строка данных не соответствует типу распределения, по умолчанию возвращается ошибка. С помощью конфигурационного параметра gp_enable_segment_copy_checking проверку типа распределения можно отключить.

Данные из таблицы, полученные путем запуска команды COPY TO …​ ON SEGMENT, можно восстановить с помощью COPY FROM …​ ON SEGMENT. При этом восстанавливаемые данные распределятся по сегментам согласно типу распределения таблицы на момент генерации файлов с помощью COPY TO. Если с момента запуска COPY FROM …​ ON SEGMENT тип распределения изменился, операция COPY может завершиться ошибкой. Если на момент запуска COPY FROM …​ ON SEGMENT конфигурационному параметру gp_enable_segment_copy_checking присвоено значение false, может потребоваться ручное перераспределение данных таблицы.

При копировании данных из таблицы, имеющей реплицированное распределение (DISTRIBUTED REPLICATED), на сегмент-хостах создаются файлы, содержащие все строки из таблицы.

Более подробную информацию о распределении данных можно получить в статье Распределение данных.

Примеры

В данных примерах команда COPY используется для копирования содержимого четырех файлов customers_0.csv — customers_3.csv в таблицу customers, а из таблицы customers — в файлы данных. Файлы располагаются в каталоге /tmp на каждом сегмент-хосте.

Для просмотра данных о конфигурации сегментов и местоположении каталогов данных выполните запрос к системному представлению gp_segment_configuration:

SELECT content,hostname,datadir FROM gp_segment_configuration;

Вывод должен выглядеть следующим образом:

 content |  hostname   |        datadir
---------+-------------+-----------------------
       -1|     mdw     | /data1/master/gpseg-1
        0|     sdw1    | /data1/primary/gpseg0
        0|     sdw2    | /data1/mirror/gpseg0
        1|     sdw1    | /data1/primary/gpseg1
        1|     sdw2    | /data1/mirror/gpseg1
        2|     sdw2    | /data1/primary/gpseg2
        2|     sdw1    | /data1/mirror/gpseg2
        3|     sdw2    | /data1/primary/gpseg3
        3|     sdw1    | /data1/mirror/gpseg3
       -1|     smdw    | /data1/master/gpseg-1
  1. В каталоге /tmp на каждом сегмент-хосте создайте файлы customers_<SEGID>.csv, где <SEGID> соответствует идентификатору контента текущего сегмента:

    • customers_0.csv:

      id,first_name,last_name,email,address
      1,John,Doe,john.doe@example.com,123 Elm Street
    • customers_1.csv:

      id,first_name,last_name,email,address
      2,Jane,Smith,jane.smith@example.com,456 Oak Street
    • customers_2.csv:

      id,first_name,last_name,email,address
      3,Bob,Brown,bob.brown@example.com,789 Pine Street
    • customers_3.csv:

      id,first_name,last_name,email,address
      4,Rob,Stuart,rob.stuart@example.com,119 Willow Street
  2. Очистите таблицу customers:

    TRUNCATE TABLE customers;
  3. Выполните команду COPY FROM. Укажите CSV в качестве формата данных и включите пропуск заголовка (HEADER):

    COPY customers FROM '/tmp/customers_<SEGID>.csv'
    CSV HEADER
    ON SEGMENT;
  4. Выполните запрос к таблице customers:

    TABLE customers;

    Вывод должен выглядеть следующим образом:

     id | first_name | last_name |         email          |      address
    ----+------------+-----------+------------------------+-------------------
      1 | John       | Doe       | john.doe@example.com   | 123 Elm Street
      2 | Jane       | Smith     | jane.smith@example.com | 456 Oak Street
      3 | Bob        | Brown     | bob.brown@example.com  | 789 Pine Street
      4 | Rob        | Stuart    | rob.stuart@example.com | 119 Willow Street
  1. Очистите таблицу customers и заполните ее данными:

    TRUNCATE TABLE customers;
    
    INSERT INTO customers (id, first_name, last_name, email, address)
    VALUES (1,'John','Doe','john.doe@example.com','123 Elm Street'),
           (2,'Jane','Smith','jane.smith@example.com','456 Oak Street'),
           (3,'Bob','Brown','bob.brown@example.com','789 Pine Street'),
           (4,'Rob','Stuart','rob.stuart@example.com','119 Willow Street');
  2. Выполните команду COPY TO.

    COPY customers TO '/tmp/customers_<SEGID>.csv'
    CSV HEADER
    ON SEGMENT;
  3. Проверьте содержимое файлов customers_0.csv — customers_3.csv, созданных в каталоге /tmp на каждом сегмент-хосте:

    $ cat /tmp/customers_0.csv && cat /tmp/customers_1.csv
    $ cat /tmp/customers_2.csv && cat /tmp/customers_3.csv

    Вывод должен выглядеть следующим образом:

    id,first_name,last_name,email,address
    1,John,Doe,john.doe@example.com,123 Elm Street
    
    id,first_name,last_name,email,address
    2,Jane,Smith,jane.smith@example.com,456 Oak Street
    
    id,first_name,last_name,email,address
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    
    id,first_name,last_name,email,address
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street

Запуск в режиме изоляции ошибок

По умолчанию работа команды COPY прекращается после первой ошибки: выполнение команды прерывается и загрузки данных не происходит. Запуск в режиме изоляции ошибок для одной строки позволяет Greengage DB пропускать строки с ошибками в формате данных, загружая при этом корректно отформатированные строки.

Для запуска команды COPY FROM в режиме изоляции ошибок для одной строки используйте выражение SEGMENT REJECT LIMIT:

COPY <table_name> [(<column_name> [, ...])]
FROM {'<filename>' | PROGRAM '<command>' | STDIN}
[ [ WITH ] ( <option> [, ...] ) ]
[LOG ERRORS] SEGMENT REJECT LIMIT <count> [ ROWS | PERCENT ]
[ ON SEGMENT ]

Во время выполнения загрузки строки с ошибками в формате данных будут пропускаться до тех пор, пока их количество не достигнет предельного значения (<count>) на любом сегменте кластера. Обратите внимание, что предельное значение применяется отдельно к каждому сегменту, а не ко всей операции загрузки. В качестве предельного значения можно указать как количество строк (по умолчанию), так и процент от общего количества строк (от 1 до 100). Если указан процент строк (PERCENT), подсчет некорректных строк начинается только после обработки их общего количества, указанного в параметре gp_reject_percent_threshold (по умолчанию 300).

Если предельное значение не достигнуто, все корректные строки загружаются в таблицу, а некорректные — пропускаются.

ПРИМЕЧАНИЕ

Режим изоляции ошибок для одной строки применяется только к файлам, содержащим ошибки форматирования данных. Если в данных содержатся ошибки, связанные, например, с ограничением уникальности, ограничением NOT NULL или ограничением-проверкой (CHECK), операция прерывается и загрузки данных не происходит.

Если выражение SEGMENT REJECT LIMIT еще не сработало, операция COPY прерывается и откатывается, если отклонены первые 1000 строк данных. Это значение можно изменить с помощью параметра gp_initial_bad_row_limit.

С помощью выражения LOG ERRORS можно сохранять информацию об ошибках в строках данных для последующего изучения. Информация хранится внутри Greengage DB, а чтобы просмотреть ее, воспользуйтесь встроенной SQL-функцией gp_read_error_log(), передав в качестве аргумента имя таблицы (<table_name>).

SELECT gp_read_error_log('<table_name>');
                                                                         gp_read_error_log
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
 ("2025-06-11 01:01:52.80594+03",customers,<stdin>,2,,"invalid input syntax for integer: ""John"", column id","John,Doe,john.doe@example.com,123 Elm Street",)
 ("2025-06-11 01:02:35.075181+03",customers,<stdin>,3,,"invalid input syntax for integer: ""Jane"", column id","Jane,Smith,jane.smith@example.com,456 Oak Street",)
(2 rows)

Пример

В данном примере команда COPY используется для копирования содержимого файла customers.csv в таблицу БД customers. В данных файла содержатся ошибки форматирования — поэтому для запуска в режиме изоляции ошибок используется выражение SEGMENT REJECT LIMIT. Выражение LOG ERRORS используется для логирования ошибок загрузки.

  1. В каталоге /tmp мастер-хоста создайте файл customers.csv. Первые две строки данных в файле отформатированы неверно: в них отсутствуют значения в колонке id.

    id,first_name,last_name,email,address
    John,Doe,john.doe@example.com,123 Elm Street
    Jane,Smith,jane.smith@example.com,456 Oak Street
    3,Bob,Brown,bob.brown@example.com,789 Pine Street
    4,Rob,Stuart,rob.stuart@example.com,119 Willow Street
  2. Очистите таблицу customers:

    TRUNCATE TABLE customers;
  3. Выполните команду COPY FROM. В выражении WITH укажите CSV в качестве формата данных и включите пропуск заголовка (HEADER). Укажите выражение LOG ERRORS, а в выражении SEGMENT REJECT LIMIT установите значение 3:

    COPY customers FROM '/tmp/customers.csv'
    WITH (FORMAT CSV,HEADER)
    LOG ERRORS SEGMENT REJECT LIMIT 3;
  4. Выполните запрос к таблице customers:

    TABLE customers;

    В выводе должно содержаться две строки, а неверно отформатированные строки должны быть пропущены:

     id | first_name | last_name |         email          |      address
    ----+------------+-----------+------------------------+-------------------
      3 | Bob        | Brown     | bob.brown@example.com  | 789 Pine Street
      4 | Rob        | Stuart    | rob.stuart@example.com | 119 Willow Street
  5. Для просмотра информации об ошибках вызовите функцию gp_read_error_log(), передав в качестве аргумента имя таблицы (customers):

    SELECT t.linenum, t.errmsg FROM gp_read_error_log('customers') t;

    Вывод должен выглядеть следующим образом:

     linenum |                       errmsg
    ---------+-----------------------------------------------------
           2 | invalid input syntax for integer: "John", column id
           3 | invalid input syntax for integer: "Jane", column id
    (2 rows)

Использование двоичного формата

При работе с командой COPY в качестве формата данных можно указать BINARY, что позволяет читать или записывать данные в двоичном формате, а не текстовом. Данные в этом формате обрабатываются быстрее, чем в текстовом или CSV, но менее переносимы между архитектурами машин и версиями Greengage DB.

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

Использование выражений для указания формата (DELIMITER, NULL, HEADER, QUOTE, ESCAPE и ENCODING) в случае двоичного формата не поддерживается.

ПРИМЕЧАНИЕ

При использовании данных в двоичном формате запуск COPY FROM в режиме изоляции ошибок не поддерживается.

Двоичный формат включает в себя заголовок файла, ноль или более записей, содержащих данные строк, и окончание файла. Для заголовков и данных принят сетевой порядок байт (первым следует наиболее значимый байт).

Заголовок файла

Заголовок файла содержит 15 байт фиксированных полей, за которыми следует область расширения заголовка переменной длины. Используются следующие фиксированные поля:

  • Сигнатура — последовательность из 11 байт PGCOPY\n\377\r\n\0. Обратите внимание, что нулевой байт является обязательной частью сигнатуры. Сигнатура позволяет легко выявить файлы, испорченные при передаче, не сохраняющей все 8 бит данных. Она изменится при прохождении через фильтры, меняющие концы строк, отбрасывающие нулевые байты или старшие биты, либо добавляющие четность.

  • Поле флагов — 32-битная маска, обозначающая важные аспекты формата файла. Биты нумеруются от 0 (наименее значимый бит, LSB) до 31 (наиболее значимый бит, MSB). Обратите внимание, что поле хранится в сетевом порядке байт (наиболее значащий байт следует первым), как и все целочисленные поля в этом формате. Биты 16–31 зарезервированы для обозначения критичных особенностей формата; обработчик должен прервать чтение, встретив любой неожиданный бит в этом диапазоне. Биты 0–15 зарезервированы для обозначения особенностей, связанных с обратной совместимостью; обработчик может игнорировать любые неожиданные биты в этом диапазоне. В настоящее время определен только один битовый флаг, остальные должны быть равны 0.

    Бит 16: при значении 1 в данные включается OID, а при 0 — не включается. Системные столбцы OID больше не поддерживаются, но в формате сохраняется этот индикатор.

  • Длина области расширения заголовка — целое 32-битное число, определяющее длину в байтах остального заголовка, не включая само это значение. В настоящее время содержит 0, и сразу за ним следует первая запись. В будущих изменениях формата в заголовок могут быть добавлены дополнительные данные. Обработчик должен пропускать все неизвестные расширенные данные заголовка. Область расширения заголовка предусмотрена для размещения последовательности самоопределяемых блоков. Поле флагов не должно содержать указаний о том, что содержится в области расширения. Точное содержимое области расширения может быть определено в будущих версиях.

Записи

Каждая запись начинается с 16-битного целого числа, определяющего количество полей в записи. В настоящее время во всех записях должно быть одинаковое число полей, но в будущем это может измениться. Затем для каждого поля в записи указывается 32-битная длина поля, за которой следует это количество байт с данными поля. Значение длины не включает свой размер и может быть равно нулю. Специальное значение -1 обозначает, что в поле содержится NULL. В случае с NULL за длиной не следуют байты данных.

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

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

Если в файл включены OID, поле OID следует немедленно за числом, определяющим количество полей. Это обычное поле, но оно не учитывается в количестве полей. В частности, оно содержит слово, определяющее длину, что позволит обрабатывать OID длиной 4 и 8 байт и даст возможность отображать OID как NULL, если это потребуется.

Окончание файла

Окончание файла состоит из 16-битного целого, содержащего -1. Это позволяет легко отличить его от счетчика полей в записи. Обработчик, читающий файл, должен выдать ошибку, если число полей в записи не равно -1 или ожидаемому числу столбцов. Это обеспечивает дополнительную проверку синхронизации данных.

Описание выражений и параметров

Выражение / Параметр Описание

BINARY

Включает режим чтения или записи данных в двоичном формате.

Указать двоичный формат также можно с помощью выражения FORMAT следующим образом: FORMAT 'binary'.

Более подробную информацию можно получить в разделе Использование двоичного формата

<table_name>

Имя существующей таблицы

<column_name>

Опциональный список колонок для копирования.

Если список указан, команда COPY скопирует в файл или из файла только содержимое указанных колонок. При использовании COPY FROM в колонки таблицы, не указанные в списке, будут записаны значения по умолчанию.

Если список не указан, копируются все колонки таблицы

<query>

Команда SELECT или VALUES, результат выполнения которой будет скопирован. Обратите внимание, что запрос должен быть заключен в скобки

<filename>

Путь ко входному или выходному файлу.

В качестве пути входного файла можно использовать абсолютный или относительный путь, а в качестве пути выходного файла — только абсолютный путь. Файл должен быть доступен на мастер-хосте. Путь должен указывать на расположение в файловой системе мастер-хоста.

Более подробную информацию можно получить в разделе Загрузка данных из файлов / в файлы

PROGRAM '<command>'

Команда для запуска.

При использовании COPY FROM входные данные поступают из стандартного вывода указанной команды, а при использовании COPY TO — записываются в стандартный ввод команды. Команда должна быть указана так, как если бы она была непосредственно введена на мастер-хосте Greengage DB, и должна быть исполняемой суперпользователем.

Более подробную информацию можно получить в разделе Загрузка данных с помощью программы

STDIN | STDOUT

STDIN указывает, что ввод данных осуществляется из клиентского приложения. STDOUT указывает, что вывод данных осуществляется в клиентское приложение.

Использование выражения ON SEGMENT совместно с STDIN или STDOUT не поддерживается.

Более подробную информацию можно получить в разделе Загрузка данных через стандартные потоки ввода / вывода

WITH <option>

Перечисляет дополнительные опции, описанные ниже

FORMAT <'text' | 'csv' | 'binary'>

Указывает формат данных и может принимать значения text, csv или binary.

Указать двоичный формат также можно с помощью специального ключевого слова BINARY следующим образом:

COPY BINARY <table_name> [(<column_name> [, ...])]
...

Более подробную информацию о форматах данных можно получить в статье Форматирование внешних данных

OIDS [ <boolean> ]

Указывает, копировать ли идентификатор объекта (OID) для каждой строки.

Возвращается ошибка, если OIDS указан для таблицы, которая не имеет OID, или при копировании запроса

FREEZE [ <boolean> ]

Указывает, что копирование данных происходит с замораживанием строк, как если бы была выполнена команда VACUUM FREEZE. Это может повысить производительность первоначальной загрузки данных. Строки замораживаются только в случае, если таблица, в которую выполняется загрузка, создана или опустошена в текущей подтранзакции, нет открытых курсоров и нет более старых снепшотов, удерживаемых этой транзакцией.

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

Более подробную информацию об операции VACUUM можно получить в статье Удаление устаревших строк с помощью VACUUM

DELIMITER '<delimiter_character>'

Указывает ASCII-символ, использующийся в качестве разделителя. Разделитель должен располагаться между полями, но не в начале и не в конце строки.

Вы также можете указать непечатаемый ASCII-символ или Unicode-символ, например \x1B или \u001B. Для непечатаемых символов также поддерживается синтаксис экранирования строк вида E'<код символа>'. ASCII- или Unicode-символ должен быть заключен в одинарные кавычки, например, E'\x1B' или E'\u001B'.

Для текстовых файлов по умолчанию используется знак табуляции (0x09).

Для CSV-файлов по умолчанию используется знак запятой (,).

Более подробную информацию можно получить в разделе Форматирование столбцов

NULL '<null string>'

Указывает строку, обозначающую null-значение — неизвестное значение колонки или поля.

Для текстовых файлов по умолчанию используется строка \N.

Для CSV-файлов по умолчанию используется пустое значение, не заключенное в кавычки.

Более подробную информацию можно получить в разделе Обработка NULL-значений

HEADER [ <boolean> ]

Указывает на наличие заголовка в файле данных.

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

QUOTE '<quote_character>'

Указывает символ кавычек. По умолчанию используется знак двойных кавычек (")

NEWLINE '<newline_character>'

Указывает символ переноса строки и принимает значения LF (символ перевода строки, 0x0A), CR (символ возврата каретки, 0x0D) или CR, совмещенный с LF (CRLF, 0x0D 0x0A).

Если значение не указано, используется символ переноса строки, которым заканчивается первая строка файла данных.

Более подробную информацию можно получить в разделе Форматирование строк

ESCAPE '<escape_character>'

Указывает символ экранирования.

Для текстовых файлов по умолчанию используется знак обратной косой черты (\). Экранирование можно отключить, указав значение OFF.

Для CSV-файлов по умолчанию используется знак кавычек (").

Более подробную информацию можно получить в разделе Символы экранирования

FORCE_QUOTE { ( <column_name> [, …​] ) | * }

Заключает в кавычки все отличные от NULL значения в указанных колонках.

Если в качестве значения указан символ *, все отличные от NULL значения заключаются в кавычки во всех колонках. Значения NULL в кавычки не заключаются

FORCE_NOT_NULL ( <column_name> [, …​] )

Позволяет обрабатывать значения полей как заключенные в кавычки. Так как null-значение по умолчанию — пустое значение, не заключенное в кавычки, это позволяет обрабатывать отсутствующие значения как пустые строки

FORCE_NULL ( <column_name> [, …​] )

Сопоставляет значения указанных столбцов с null-строкой. При совпадении значение устанавливается в NULL, даже если оно заключено в кавычки. По умолчанию, когда null-строка пуста, заключенная в кавычки пустая строка преобразуется в NULL

ENCODING '<encoding_name>'

Определяет кодировку символов исходных данных. Если значение не указано, используется клиентская кодировка по умолчанию.

Более подробную информацию можно получить в разделе Character encoding

FILL MISSING FIELDS

Устанавливает значения NULL для пропущенных полей в конце строки или записи. Если значение не установить, в подобных случаях будет возвращена ошибка. Пустые строки, поля с ограничением NOT NULL и конечные разделители в любом случае вернут ошибку

LOG ERRORS

Включает запись в лог информации о строках данных, содержащих ошибки форматирования.

Информация хранится внутри Greengage DB, а чтобы просмотреть ее, воспользуйтесь встроенной SQL-функцией gp_read_error_log(), передав в качестве аргумента имя таблицы (<table_name>).

Более подробную информацию можно получить в разделе Запуск в режиме изоляции ошибок

SEGMENT REJECT LIMIT <count> [ ROWS | PERCENT ]

Запускает команду COPY FROM в режиме изоляции ошибок для одной строки. В качестве значения можно указать общее количество строк (по умолчанию) либо процент от общего количества строк (от 1 до 100).

Более подробную информацию можно получить в разделе Запуск в режиме изоляции ошибок

IGNORE EXTERNAL PARTITIONS

Если выражение указано, при копировании из партиционированных таблиц данные не копируются из конечных дочерних партиций, являющихся внешними таблицами. Соответствующее сообщение добавляется в лог-файл.

В противном случае, если выражение не указано и Greengage DB пытается скопировать данные из конечной дочерней партиции, являющейся внешней таблицей, возвращается ошибка.

Чтобы скопировать данные из партиционированной таблицы с конечной дочерней партицией, являющейся внешней таблицей, выберите данные для копирования с помощью SQL-запроса

ON SEGMENT

Указывает, что загрузка или выгрузка данных осуществляется через отдельные файлы, расположенные на сегмент-хостах.

Более подробную информацию можно получить в разделе Использование выражения ON SEGMENT