使用二进制格式的EBCDIC文件的外部表Oracle-错误KUP-03003

问题描述

我的环境:Red Hat版本7上的Oracle 12.2(数据库字符集AL32UTF8)

我在处理一个外部表时遇到了一个大问题,该外部表指向一个来自AS400系统的EBCDIC格式的文件。我最终可以弄清楚记录的长度和每个字段的位置。我现在的问题是某些字段是COMP-3格式的数据包,我正为错误KUP-03003苦苦挣扎。

让我告诉你会发生什么。之所以将它们全部加载为varchar2列,是因为稍后我有一个过程可以将每个字段转换为最终批处理表中要使用的最终数据表的正确数据类型格式。

1。这是外部表定义

DROP TABLE CPL_HIST.EXT_L027_AS_RPLMREP purge;

CREATE TABLE CPL_HIST.EXT_L027_AS_RPLMREP
( 
  LMZMDT         VARCHAR2(4000 CHAR),LMORNB         VARCHAR2(4000 CHAR),LMH6NE         VARCHAR2(4000 CHAR),LMG9VA         VARCHAR2(4000 CHAR),LMHAVA         VARCHAR2(4000 CHAR),LMA8PS         VARCHAR2(4000 char),LMALEU         VARCHAR2(4000 char),LMHBVA         VARCHAR2(4000 char),LMHCVA         VARCHAR2(4000 char),LMIHNE         VARCHAR2(4000 char),LMHDVA         VARCHAR2(4000 char),LMA9PS         VARCHAR2(4000 char),LMBAPS         VARCHAR2(4000 char),LMO1TT         VARCHAR2(4000 char),LMAMEU         VARCHAR2(4000 char),LMHEVA         VARCHAR2(4000 char),LMFINB         VARCHAR2(4000 char),LMECNE         VARCHAR2(4000 char),LMYXNF         VARCHAR2(4000 char),LMD5EU         VARCHAR2(4000 char),LMSTVA         VARCHAR2(4000 char),LMSUVA         VARCHAR2(4000 char),LMQECE         VARCHAR2(4000 char),LMU4VA         VARCHAR2(4000 char),LMU5VA         VARCHAR2(4000 char),LMDVDT         VARCHAR2(4000 char),LMDWDT         VARCHAR2(4000 char),LMAJTM         VARCHAR2(4000 char),LMLPXT         VARCHAR2(4000 char),LMLQXT         VARCHAR2(4000 char),LMNUST         VARCHAR2(4000 char)
  )
ORGANIZATION EXTERNAL
( TYPE oracle_loader
  DEFAULT DIRECTORY DIR_CPL_EXT
  ACCESS PARAMETERS
 (
 RECORDS FIXED 176 CHARACTERSET WE8EBCDIC500
 BADFILE 'EXT_L027_AS_RPLMREP.bad'
 DISCARDFILE 'EXT_L027_AS_RPLMREP.dsc'
 LOGFILE 'EXT_L027_AS_RPLMREP.log'
 READSIZE 1048576 
 FIELDS LTRIM
 MISSING FIELD VALUES ARE NULL
 REJECT ROWS WITH ALL NULL FIELDS
 (
LMZMDT (1:3)          CHAR,LMORNB (4:9)          DECIMAL(10,0),LMH6NE (10:11)        DECIMAL(2,LMG9VA (12:18)        DECIMAL(7,2),LMHAVA (19:25)        DECIMAL(7,LMA8PS (26:28)        DECIMAL(3,LMALEU (29:38)        CHAR,LMHBVA (39:45)        DECIMAL(7,LMHCVA (46:52)        DECIMAL(7,LMIHNE (53:53)        DECIMAL(1,LMHDVA (54:60)        DECIMAL(7,LMA9PS (61:63)        DECIMAL(3,LMBAPS (64:66)        DECIMAL(3,LMO1TT (67:76)        CHAR,LMAMEU (77:86)        CHAR,LMHEVA (87:93)        DECIMAL(7,LMFINB (94:95)        DECIMAL(2,LMECNE (96:100)       DECIMAL(5,LMYXNF (101:105)      DECIMAL(5,LMD5EU (106:115)      CHAR,LMSTVA (116:122)      DECIMAL(7,LMSUVA (123:129)      DECIMAL(7,LMQECE (130:131)      CHAR,LMU4VA (132:134)      DECIMAL(3,3),LMU5VA (135:142)      DECIMAL(8,LMDVDT (143:146)      DECIMAL(4,LMDWDT (147:150)      DECIMAL(4,LMAJTM (151:154)      DECIMAL(4,LMLPXT (155:164)      CHAR,LMLQXT (165:174)      CHAR,LMNUST (175:176)      CHAR
 )
 )
 location
 (
 'RPLMREP.bin'
 )
 ) 
 REJECT LIMIT 0
 /

2。然后我创建表格

SQL*Plus: Release 12.2.0.1.0 Production on Fri Sep 11 13:13:03 2020

Copyright (c) 1982,2016,Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production


Table dropped.


Table created.

您在上面看到的是我在SAS程序中对同一表的定义,该表对待相同文件没有问题。现在,如果我尝试读取表中的第一个字段,则表中的最后一个字段会出错。

SQL> select LMZMDT from cpl_hist.EXT_L027_AS_RPLMREP a where a.LMZMDT is not null and rownum < 10 ;
select LMZMDT from cpl_hist.EXT_L027_AS_RPLMREP a where a.LMZMDT is not null and rownum < 10
*
ERROR at line 1:
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-03003: absolute end(154) - start(151) != fieldlength (3) for field LMAJTM

很明显,如果我将所有字段都放入CHAR,则不会加载所有COMP-3小数数据包。我所做的测试是通过将所有字段都放入char中,然后开始逐一更改来验证哪些字段是问题。我不明白的是为什么长度与这些字段的规范及其所占据的位置不匹配。

让我给你看一个例子。我仅在前4个字段中以正确的格式创建表

LMZMDT (1:3)          CHAR,LMA8PS (26:28)        CHAR,LMHBVA (39:45)        CHAR,LMHCVA (46:52)        CHAR,LMIHNE (53:53)        CHAR,LMHDVA (54:60)        CHAR,LMA9PS (61:63)        CHAR,LMBAPS (64:66)        CHAR,LMHEVA (87:93)        CHAR,LMFINB (94:95)        CHAR,LMECNE (96:100)       CHAR,LMYXNF (101:105)      CHAR,LMSTVA (116:122)      CHAR,LMSUVA (123:129)      CHAR,LMU4VA (132:134)      CHAR,LMU5VA (135:142)      CHAR,LMDVDT (143:146)      CHAR,LMDWDT (147:150)      CHAR,LMAJTM (151:154)      CHAR,LMNUST (175:176)      CHAR                 

以这种格式创建表格后,我得到了

SQL> select LMZMDT from cpl_hist.EXT_L027_AS_RPLMREP a where a.LMZMDT is not null and rownum < 10 ;
select LMZMDT from cpl_hist.EXT_L027_AS_RPLMREP a where a.LMZMDT is not null and rownum < 10
*
ERROR at line 1:
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-03003: absolute end(25) - start(19) != fieldlength (4) for field LMHAVA

但是,如果我将定义更改为(仅前四个字段)

LMZMDT (1:3)          CHAR,LMG9VA (12:18)        DECIMAL(10,LMHAVA (19:25)        DECIMAL(10,

然后查询将一直运行到第四个字段。

SQL>  select LMZMDT from cpl_hist.EXT_L027_AS_RPLMREP a where a.LMZMDT is not null and rownum < 10 ;

LMZMDT
--------------------------------------------------------------------------------
AKB
AKB
AKB
AKB
AKB
AKB
AKB
AKB
AKB

9 rows selected.

SQL> select LMORNB from cpl_hist.EXT_L027_AS_RPLMREP a where a.LMZMDT is not null and rownum < 10 ;

LMORNB
--------------------------------------------------------------------------------
1020019630
1020083310
1020087030
1020120440
1020121681
1020127470
1020147350
1020169610
1020223080

SQL> select LMHAVA from cpl_hist.EXT_L027_AS_RPLMREP a where a.LMZMDT is not null and rownum < 10 ;

LMHAVA
--------------------------------------------------------------------------------
.00
.00
.00
.00
.00
.00
.00
.00
.00

9 rows selected.

由于我无法读取文件以查看位置是否符合规范。我有一些问题:

  • 为什么如果我只输入DECIMAL而未指定精度或小数位数,则负载不起作用,并且我遇到相同的KUP错误?
  • 我必须为每个字段执行此操作吗?我很努力,因为有些表的列超过100个。
  • 是否有更好的方法通过EBCDIC代码页从外部表中读取数据包的十进制字段?或任何可以将该文件转换为ascii的工具,我都可以检查其位置。
  • 为什么在其他系统中起作用的假定长度对于十进制数据类型无效?
  • 我想我正在为文件(WE8EBCDIC500)使用正确的字符集。我可以吗?

希望可以为您提供帮助 预先谢谢你。

解决方法

原因是ECBDIC中的压缩小数通常包含诸如“ 0C”之类的字符,它们无法装入表的deciaml列中。

唯一的建议是首先将EBCDIC文件转换为UTF-8格式。

看看这个:

Conversion from EBCDIC to UTF8 in Linux

这是iconv支持的EBCDIC代码的列表:

IBM-037欧洲 IBM-1025西里尔字母 IBM-1026拉丁语5(土耳其) IBM-1027日本拉丁语 IBM-1047开放系统 IBM-1112波罗的海 IBM-1122爱沙尼亚 IBM-1140芬兰,瑞典 IBM-1141奥地利,德国 IBM-1142丹麦,挪威 IBM-1143美国 IBM-1144意大利 IBM-1145西班牙,讲西班牙语的拉丁美洲 IBM-1146英国 IBM-1147法国 IBM-1148比利时,瑞士 IBM-1149冰岛 IBM-1388中国 IBM-273德国 IBM-274比利时 IBM-277丹麦-挪威 IBM-278瑞典-芬兰 IBM-280意大利 IBM-284西班牙-拉丁美洲 IBM-285英国 IBM-290日本片假名 IBM-297法国 IBM-424以色列 IBM-500国际 IBM-838泰语 IBM-871冰岛 IBM-875希腊文 IBM-924 IBM500 / IBM1047与欧元 IBM-930日语片假名/汉字多字节 IBM-933韩国 IBM-935中国 IBM-937台湾 IBM-939日本扩展 IBM-970拉丁2 IBM-971冰岛 IBM-975希腊

尝试一下。

或oracle函数:

CONVERT(string1,char_set_to [,char_set_from]) 例如: convert(变量,'UTF8','WE8EBCDIC500')

如果您在使用iconv时遇到麻烦,只需使用一个字段创建外部表,然后将任何行的convert(...)选择到另一个表中,或使用pl / sql过程填充新表以将转换后的行。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...