Использование символа разделителя полей ASCII 31 в качестве разделителя Postgresql COPY

Мы экспортируем данные из Postgres 9.3 в текстовый файл для загрузки в Spark.

Мы хотели бы использовать символ разделителя полей ASCII 31 в качестве разделителя вместо \ t, чтобы нам не приходилось беспокоиться об устранении проблем.

Мы можем сделать это в таком сценарии оболочки:

#!/bin/bash
DELIMITER=$'\x1F'
echo "copy ( select * from table limit 1) to STDOUT WITH DELIMITER '${DELIMITER}'" | (psql ...) > /tmp/ascii31

Но нам интересно, можно ли указать непечатаемый глиф в качестве разделителя в "чистых" postgres?

изменить: мы попытались использовать соглашение об экранировании postgres согласно http://www.postgresql.org/docs/9.3/static/sql-syntax-lexical.html

warehouse=> copy ( select * from table limit 1) to STDOUT WITH DELIMITER '\x1f';

и получил

ERROR:  COPY delimiter must be a single one-byte character

person jaegard    schedule 17.02.2015    source источник


Ответы (3)


Попробуйте добавить E перед последовательностью, которую вы пытаетесь использовать в качестве разделителя. Например, E'\x1f' вместо '\x1f'. Без E PostgreSQL будет читать '\x1f' как четыре отдельных символа, а не как шестнадцатеричную escape-последовательность, отсюда и сообщение об ошибке.

См. руководство PostgreSQL «Строковые константы с C-style Escapes » для получения дополнительной информации.

person Gregory Arenius    schedule 09.09.2015
comment
Блестящий ответ. Так важно всегда, всегда, всегда добавлять E перед любым шестнадцатеричным, регулярным или специальным символом в сценариях Postgres. Иногда это сработает и без него, но всегда будет один раз, когда этого не произойдет по непонятной причине. - person pele88; 10.12.2016

По результатам моего тестирования оба следующих действия работают:

echo "copy (select 1 a, 2 b) to stdout with delimiter u&'\\001f'"| psql;

echo "copy (select 1 a, 2 b) to stdout with delimiter e'\\x1f'"| psql;
person bgoldst    schedule 17.02.2015
comment
Хммм, ни один из них не работает в оболочке psql, оба выдают ОШИБКУ: разделитель КОПИЙ должен быть одним однобайтовым символом - person jaegard; 17.02.2015
comment
Хм, странно. Какая у вас версия postgres и какая ОС? (Я получаю psql (PostgreSQL) 9.3.5 от psql --version, работающего в Windows 8.1) - person bgoldst; 18.02.2015
comment
На самом деле, когда вы говорите «оболочка psql», вы имеете в виду, что вы скопировали текст в двойных кавычках в приведенных выше командах и вставили его в приглашение psql? Это не сработает; Двойная обратная косая черта - это escape-код в строке, заключенной в двойные кавычки оболочки, которая преобразуется в одиночную обратную косую черту перед отображением в psql. В коде, который видит psql, должна быть только одна обратная косая черта. Позвольте мне знать, если это помогает. - person bgoldst; 18.02.2015
comment
Кто-нибудь решил это? Я хочу сделать то же самое. Я получаю ERROR: invalid byte sequence for encoding "UTF8": 0x00, когда выполняю всевозможные комбинации бегства. - person squarism; 24.06.2015

Я извлек небольшой файл из Actian Matrix (ответвление Amazon Redshift, обе производные от postgres), используя эту нотацию для кода 30 символа ASCII, «Разделитель записей».

unload ('SELECT btrim(class_cd) as class_cd, btrim(class_desc) as class_desc
FROM transport.stg.us_fmcsa_carrier_classes')
to '/tmp/us_fmcsa_carrier_classes_mk4.txt'
delimiter as '\036' leader;

Это пример того, как этот файл выглядит в VI:

C^^Private Property
D^^Private Passenger Business
E^^Private Passenger Non-Business

Затем я переместил этот файл на компьютер, на котором размещен PostgreSQL 9.5 через sftp, и использовал следующую команду копирования, которая, похоже, работает хорошо:

copy fmcsa.carrier_classes
from '/tmp/us_fmcsa_carrier_classes_mk4.txt'
delimiter u&'\001E'; 

Кажется, что каждая производная от postgres и сам postgres предпочитают немного другую нотацию. Жаль, что у нас нет единого стандарта!

person Geoffrey Clark    schedule 25.04.2016