Команда 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, или записать данные в файл, запустите команду 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
, а содержимого таблицы БД — в файл.
-
В каталоге /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
-
Очистите таблицу
customers
:TRUNCATE TABLE customers;
-
Выполните команду
COPY FROM
. В выраженииWITH
укажитеCSV
в качестве формата данных и включите пропуск заголовка (HEADER
):COPY customers FROM '/tmp/customers.csv' WITH (FORMAT CSV, HEADER);
-
Выполните запрос к таблице
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
-
Очистите таблицу
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');
-
Выполните команду
COPY TO
. В выраженииWITH
укажитеCSV
в качестве формата данных и включите добавление заголовка (HEADER
):COPY customers TO '/tmp/customers.csv' WITH (FORMAT CSV, HEADER);
-
Проверьте содержимое файла 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
.
-
В каталоге /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
-
Очистите таблицу
customers
:TRUNCATE TABLE customers;
-
Выполните команду
COPY FROM
. В выраженииPROGRAM
укажите командуcat
. В выраженииWITH
укажитеCSV
в качестве формата данных и включите пропуск заголовка (HEADER
):COPY customers FROM PROGRAM 'cat /tmp/customers.csv' WITH (FORMAT CSV, HEADER);
-
Выполните запрос к таблице
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
-
Очистите таблицу
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');
-
Выполните команду
COPY TO
. В выраженииWITH
укажитеCSV
в качестве формата данных и включите добавление заголовка (HEADER
):COPY customers TO PROGRAM 'cat > /tmp/customers.csv' WITH (FORMAT CSV, HEADER);
-
Проверьте содержимое файла 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).
Ввод и вывод данных осуществляется с помощью клиентского терминала.
-
Очистите таблицу
customers
:TRUNCATE TABLE customers;
-
Выполните команду
COPY FROM
. В выраженииWITH
укажитеCSV
в качестве формата данных.COPY customers FROM STDIN WITH (FORMAT CSV);
-
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 \.
-
Выполните запрос к таблице
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
-
Очистите таблицу
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');
-
Выполните команду
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
, а содержимого таблицы БД — в файл.
-
В каталоге /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
-
Очистите таблицу
customers
:TRUNCATE TABLE customers;
-
Выполните команду
\copy from
. В выраженииwith
укажитеcsv
в качестве формата данных и включите пропуск заголовка (header
):\copy customers from '/tmp/customers.csv' with (format csv,header)
-
Выполните запрос к таблице
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
-
Очистите таблицу
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');
-
Выполните команду
\copy to
. В выраженииwith
укажитеcsv
в качестве формата данных и включите добавление заголовка (header
):\copy customers to '/tmp/customers.csv' with (format csv,header)
-
Проверьте содержимое файла 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
используется для копирования содержимого четырех файлов 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
-
В каталоге /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
-
-
Очистите таблицу
customers
:TRUNCATE TABLE customers;
-
Выполните команду
COPY FROM
. УкажитеCSV
в качестве формата данных и включите пропуск заголовка (HEADER
):COPY customers FROM '/tmp/customers_<SEGID>.csv' CSV HEADER ON SEGMENT;
-
Выполните запрос к таблице
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
-
Очистите таблицу
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');
-
Выполните команду
COPY TO
.COPY customers TO '/tmp/customers_<SEGID>.csv' CSV HEADER ON SEGMENT;
-
Проверьте содержимое файлов 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
используется для логирования ошибок загрузки.
-
В каталоге /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
-
Очистите таблицу
customers
:TRUNCATE TABLE customers;
-
Выполните команду
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;
-
Выполните запрос к таблице
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
-
Для просмотра информации об ошибках вызовите функцию
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 |
Включает режим чтения или записи данных в двоичном формате. Указать двоичный формат также можно с помощью выражения Более подробную информацию можно получить в разделе Использование двоичного формата |
<table_name> |
Имя существующей таблицы |
<column_name> |
Опциональный список колонок для копирования. Если список указан, команда Если список не указан, копируются все колонки таблицы |
<query> |
Команда |
<filename> |
Путь ко входному или выходному файлу. В качестве пути входного файла можно использовать абсолютный или относительный путь, а в качестве пути выходного файла — только абсолютный путь. Файл должен быть доступен на мастер-хосте. Путь должен указывать на расположение в файловой системе мастер-хоста. Более подробную информацию можно получить в разделе Загрузка данных из файлов / в файлы |
PROGRAM '<command>' |
Команда для запуска. При использовании Более подробную информацию можно получить в разделе Загрузка данных с помощью программы |
STDIN | STDOUT |
Использование выражения Более подробную информацию можно получить в разделе Загрузка данных через стандартные потоки ввода / вывода |
WITH <option> |
Перечисляет дополнительные опции, описанные ниже |
FORMAT <'text' | 'csv' | 'binary'> |
Указывает формат данных и может принимать значения Указать двоичный формат также можно с помощью специального ключевого слова
Более подробную информацию о форматах данных можно получить в статье Форматирование внешних данных |
OIDS [ <boolean> ] |
Указывает, копировать ли идентификатор объекта (OID) для каждой строки. Возвращается ошибка, если |
FREEZE [ <boolean> ] |
Указывает, что копирование данных происходит с замораживанием строк, как если бы была выполнена команда Обратите внимание, что в остальных сессиях данные будут видны сразу после их успешной загрузки. Это нарушает обычные правила видимости MVCC, поэтому следует учитывать потенциальные связанные с этим проблемы. Более подробную информацию об операции |
DELIMITER '<delimiter_character>' |
Указывает ASCII-символ, использующийся в качестве разделителя. Разделитель должен располагаться между полями, но не в начале и не в конце строки. Вы также можете указать непечатаемый ASCII-символ или Unicode-символ, например Для текстовых файлов по умолчанию используется знак табуляции ( Для CSV-файлов по умолчанию используется знак запятой ( Более подробную информацию можно получить в разделе Форматирование столбцов |
NULL '<null string>' |
Указывает строку, обозначающую null-значение — неизвестное значение колонки или поля. Для текстовых файлов по умолчанию используется строка Для CSV-файлов по умолчанию используется пустое значение, не заключенное в кавычки. Более подробную информацию можно получить в разделе Обработка NULL-значений |
HEADER [ <boolean> ] |
Указывает на наличие заголовка в файле данных. Если используются несколько файлов с данными, то все они должны иметь заголовок. По умолчанию предполагается, что заголовок в файлах данных отсутствует |
QUOTE '<quote_character>' |
Указывает символ кавычек. По умолчанию используется знак двойных кавычек ( |
NEWLINE '<newline_character>' |
Указывает символ переноса строки и принимает значения Если значение не указано, используется символ переноса строки, которым заканчивается первая строка файла данных. Более подробную информацию можно получить в разделе Форматирование строк |
ESCAPE '<escape_character>' |
Указывает символ экранирования. Для текстовых файлов по умолчанию используется знак обратной косой черты ( Для CSV-файлов по умолчанию используется знак кавычек ( Более подробную информацию можно получить в разделе Символы экранирования |
FORCE_QUOTE { ( <column_name> [, …] ) | * } |
Заключает в кавычки все отличные от Если в качестве значения указан символ |
FORCE_NOT_NULL ( <column_name> [, …] ) |
Позволяет обрабатывать значения полей как заключенные в кавычки. Так как null-значение по умолчанию — пустое значение, не заключенное в кавычки, это позволяет обрабатывать отсутствующие значения как пустые строки |
FORCE_NULL ( <column_name> [, …] ) |
Сопоставляет значения указанных столбцов с null-строкой.
При совпадении значение устанавливается в |
ENCODING '<encoding_name>' |
Определяет кодировку символов исходных данных. Если значение не указано, используется клиентская кодировка по умолчанию. Более подробную информацию можно получить в разделе Character encoding |
FILL MISSING FIELDS |
Устанавливает значения |
LOG ERRORS |
Включает запись в лог информации о строках данных, содержащих ошибки форматирования. Информация хранится внутри Greengage DB, а чтобы просмотреть ее, воспользуйтесь встроенной SQL-функцией Более подробную информацию можно получить в разделе Запуск в режиме изоляции ошибок |
SEGMENT REJECT LIMIT <count> [ ROWS | PERCENT ] |
Запускает команду Более подробную информацию можно получить в разделе Запуск в режиме изоляции ошибок |
IGNORE EXTERNAL PARTITIONS |
Если выражение указано, при копировании из партиционированных таблиц данные не копируются из конечных дочерних партиций, являющихся внешними таблицами. Соответствующее сообщение добавляется в лог-файл. В противном случае, если выражение не указано и Greengage DB пытается скопировать данные из конечной дочерней партиции, являющейся внешней таблицей, возвращается ошибка. Чтобы скопировать данные из партиционированной таблицы с конечной дочерней партицией, являющейся внешней таблицей, выберите данные для копирования с помощью SQL-запроса |
ON SEGMENT |
Указывает, что загрузка или выгрузка данных осуществляется через отдельные файлы, расположенные на сегмент-хостах. Более подробную информацию можно получить в разделе Использование выражения ON SEGMENT |