PostgreSQL:如何使用GnuCOBOL将不兼容(UTF8)的原始字节存储为bytea?

PostgreSQL:如何使用GnuCOBOL将不兼容(UTF8)的原始字节存储为bytea?,postgresql,utf-8,gnucobol,Postgresql,Utf 8,Gnucobol,我使用的应用程序通过将32位掩码(1和0)转换为十六进制,将其作为4个字符的字段存储在数据库中。(这是一个非常旧的应用程序,因此无法更改此设置) 这在Oracle和DB2(UTF8编码)中使用得很好,但是在PostgreSQL(UTF8编码)中,当我尝试使用COBOL程序插入值时,会产生以下错误: 错误:编码“SJIS”的字节序列无效:0xa0 Binary=011010011110000110010100000 Hex=0x68270CA0 数据库编码和表定义 diginst=> \en

我使用的应用程序通过将32位掩码(1和0)转换为十六进制,将其作为4个字符的字段存储在数据库中。(这是一个非常旧的应用程序,因此无法更改此设置)

这在Oracle和DB2(UTF8编码)中使用得很好,但是在PostgreSQL(UTF8编码)中,当我尝试使用COBOL程序插入值时,会产生以下错误:

错误:编码“SJIS”的字节序列无效:0xa0

Binary=011010011110000110010100000

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,即使客户端编码和服务器编码为UTF8。但是,即使是UTF8(我在上面的代码中手动将CLIENT_ENCODING设置为“UTF8”),0xA0在UTF8字符集中也不是有效字符

从上的PostgreSQL文档

简而言之,二进制字符串适用于存储 程序员认为是“原始字节”,而字符串是 适合于存储文本

我不确定在这种情况下我做错了什么,因为
bytea
应该可以工作(根据文档)

还想知道为什么程序选择默认编码为
SJIS
,而它应该是
UTF8
。我还尝试设置环境变量
PGCLIENTENCODING=UTF8
,但它仍然给出与SJIS相同的错误

*我认为这也与主要问题有关,所以我不想就此提出单独的问题

Update:在进一步挖掘之后,DB2通过在CREATETABLE语句中为位数据添加子句
,存储原始字节(即使db编码不支持它)-

create table tab_db2 (key_part char(5) not null, raw_data char (100) for bit data); 
在Oracle中,使用的字符集是
AL32UTF8
,它支持的字符数()比
UTF8


PostgreSQL中有用于
AL32UTF8
的字符集,因此我暂时使用
LATIN1
,直到找到其他字符集。

在Oracle和DB2中使用了什么类型?实际的表模式是什么?这两个数据库都有Unicode字符串的显式类型支持,例如
nvarhar2
。他们不需要服务器编码来将
char
转换为UTF8。该应用程序使用了一种只适用于那些特定类型的黑客。您不能期望它在任何其他数据库中以相同的方式工作。类型是什么?@PanagiotisKanavos DB2对位数据的定义是
CHAR(4)
,在Oracle中
NLS\u字符集
是AL32UTF8。不确定AL32UTF8和UTF8之间有什么区别。PostgreSQL中是否有AL32UTF8的等效项?看起来您已经正确诊断了问题-Postgres似乎在将字符串转换为二进制之前验证字符串在字符集中是否有效。如果您能够将COBOL更改为
05d-MASK SQL类型为BINARY(4)
或可能的
05d-MASK S9(9)BINARY
,这可能会解决问题-但不是COBOL专家。