Приложение, которое я использую, хранит 32-битную маску (1 и 0) в качестве 4-символьного поля в базе данных путем преобразования его в шестнадцатеричное. (Это довольно старое приложение, поэтому изменить его нельзя).
Раньше это хорошо работало с Oracle & DB2 (кодировка UTF8), однако с PostgreSQL (кодировка UTF8), когда я пытаюсь вставить значение с помощью программы COBOL, которая выдает ошибку ниже:
ERROR: invalid byte sequence for encoding "SJIS": 0xa0
Binary = 01101000001001110000110010100000
Hex=0x68270CA0
Кодировка базы данных и определение таблицы
diginst=> \encoding
UTF8
diginst=> \d tab_1
Column | Type | Collation | Nullable | Default
--------+--------------+-----------+----------+---------
code | character(5) | | not null |
mask | bytea | | |
Программа COBOL
IDENTIFICATION DIVISION.
PROGRAM-ID. ENCODE.
DATE-WRITTEN. 2013-06-28.
DATA DIVISION.
WORKING-STORAGE SECTION.
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 DBNAME PIC X(30) VALUE SPACE.
01 SOC-REC-VARS.
05 D-CODE PIC X(5).
05 D-MASK PIC X(4).
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL INCLUDE SQLCA END-EXEC.
PROCEDURE DIVISION.
MAIN-RTN.
MOVE "/@diginst" TO DBNAME.
EXEC SQL
CONNECT :DBNAME
END-EXEC.
IF SQLCODE NOT = ZERO DISPLAY "ERROR CONNECTING".
MOVE "00001" TO D-CODE.
MOVE X"68270CA0" TO D-MASK.
EXEC SQL
INSERT INTO TAB_1
(CODE,
MASK)
VALUES(:D-CODE,
:D-MASK)
END-EXEC.
IF SQLCODE = ZERO DISPLAY "INSERT SUCCESSFUL"
ELSE DISPLAY "INSERT FAILED " SQLERRMC
GO TO EXIT-0.
EXEC SQL
SELECT CODE,MASK
INTO :D-CODE, :D-MASK FROM TAB_1
END-EXEC.
IF SQLCODE = ZERO DISPLAY "SELECT SUCCESSFUL"
ELSE DISPLAY "SELECT FAILED " SQLERRMC.
EXIT-0.
STOP RUN.
Не уверен, почему он выбирает кодировку как SJIS, хотя client_encoding и server_encoding имеют UTF8. Однако даже если бы это был UTF8 (я вручную сделал SET CLIENT_ENCODING TO 'UTF8' в приведенном выше коде) 0xA0 не является допустимым символом в наборе символов UTF8.
Из документации PostgreSQL по bytea
Короче говоря, двоичные строки подходят для хранения данных, которые
программист считает «необработанными байтами», тогда как символьные строки
подходит для хранения текста.
Я не уверен, что я делаю неправильно в этом случае, поскольку bytea
должен работать (согласно документации).
Также хотелось бы знать, почему программа выбирает кодировку по умолчанию как SJIS
, когда она должна быть UTF8
. Я также попытался установить переменную окружения PGCLIENTENCODING=UTF8
, но она по-прежнему выдает ту же ошибку, что и SJIS.
* Не думал задавать отдельный вопрос для этого, так как я считаю, что это тоже связано с основной проблемой.
Обновление : после еще нескольких копаний DB2 хранит необработанные байты (даже если кодировка БД не поддерживает это), добавляя предложение FOR BIT DATA
в операторе создания таблицы как-
create table tab_db2 (key_part char(5) not null, raw_data char (100) for bit data);
В Oracle используется набор символов AL32UTF8
, который поддерживает больше символов ( дополнительных символов ), чем UTF8
.
В PostgreSQL нет эквивалентного набора символов для AL32UTF8
, поэтому я прибегаю к использованию LATIN1
на данный момент, пока не найду что-то еще.