使用 C# 动态读取 COBOL 重新定义
Dynamically Reading COBOL Redefines with C#
我正在制作一个 C# 程序,它将能够动态读取用 COBOL 编写的 IBM HOST Copybook 并从中生成 SQL table。生成 table 后,我可以将文件上传到我的程序中,它将读取、从 IMB-37 转换并将文件插入 sql table。到目前为止,我几乎可以处理任何事情,尽管我 运行 遇到了 REDEFINES 的一些问题。
例如:
10 SOME-FIELD PIC 9(3) COMP-3. SCRRB205
4117 10 SOME-OTHER-FIELD REDEFINES 3041-17
4117 SOME-FIELD PIC X(2). 3041-17
我知道在这种情况下,重新定义取代了它上面的字段,尽管我不明白的是编译器如何知道它是否应该在其上使用重新定义。我假设在这种情况下是因为第一个是数字而第二个是字符,尽管在下面的示例中它们都使用字符。
05 STREET-ADDRESS.
10 ADDRESS-LINE-1 PIC X(20).
10 ADDRESS-LINE-2 PIC X(20).
05 PO-BOX REDEFINES STREET-ADDRESS PIC X(40).
我试过忽略重新定义,因为它总是需要相同数量的 space,但是在原始字段被打包而重新定义的字段没有打包的情况下,我需要知道何时解包领域。
任何对此的帮助都会很棒!
REDEFINES
将使您的任务更加困难。并不是 "compiler" 知道要使用哪个特定字段,直观上,是现有 COBOL 系统中的代码知道要使用哪个字段。会有一些指示,在另一个字段中有一些值,这将指示在特定时间使用哪些字段。
以你的第二个例子为例,因为第一个例子缺乏上下文:
05 ADDRESS-PO-BOX-FLAG PIC X.
在使用数据之前将询问该字段。直接(您可以在那里找到很多可怕的代码)或使用 88 级条件名称:
88 ADDRESS-IS-A-PO-BOX VALUE "Y". (an example only)
IF ADDRESS-IS-A-PO-BOX
some code relating to PO Boxes
ELSE
some code relating to other types of addresses
END-IF
您的第一个示例将以类似的方式处理。
REDEFINES 的 "old style" 用法,在互斥情况下使用记录上的相同存储位置。节省昂贵的存储空间。您正在使用的系统要么是 "old",要么是它的设计被错误的 "experience".
感染了
您有两个广泛的选择:复制所有条件选择的数据(以便您有两组业务逻辑保持同步);更改文件,以便每个字段占用自己的存储空间。
COMP-3(或 PACKED-DECIMAL)或 COMP/COMP-4/COMP-5/BINARY 数据类型的存在也会使您的事情复杂化。然后,您需要在字段级别为实际的 EBCDIC 数据执行 EBCDIC 到 ASCII 的操作,并执行任何必要的操作来转换或简单地获取 "computational" 数据。
另请注意,任何带符号的显示数字字段(带有以 S 开头但没有明确 "computational" 用法的 PICture 的数字字段)显然会在最后一个字节中包含 "character" 数据,因为符号被保存为最后一个字节的 "overpunch"。
请注意,二进制数据类型将是 Big Endian。
如果您收到没有 REDEFINES、没有 "computational" 字段且没有嵌入符号(或隐含的小数位)的文件,对您来说会简单得多。您的所有数据都是字符,您可以在记录级别(或在文件级别,使用您的文件传输机制)从 EBCDIC 到 ASCII。
如果您在此处查看标记为 COMP-3 的问题,您会找到对此的进一步讨论,并且如果您决定荒谬的路线(您的程序理解本机大型机 COBOL 数据项而不是普通 "text") 是唯一可行的方法,那么讨论中有许多内容您可能会觉得有用并且能够使用或应用。
如果您的公司是 "regulated" 外部的,那么在编写一行代码之前,请确保您的合规、审计和会计部门对您的设计感到满意。哎呀。迟到了。让我们希望它是制造业。
也许我可以帮助你,因为 2 年前我已经完成了你现在正在做的事情。
我不得不设计一个 MySQL 数据仓库,包括 ETL 系统,完全基于来自 RM COBOL ERP 应用程序 运行 的文件 运行 =150=]。
该应用程序有 600 多个文件,目前还不清楚其中有多少文件最终会进入数据库。大多数重要文件都在 COMP 字段上建立了索引,以使其更难,其中一个明显的要求是文件及其索引键之间的所有关系都可以在数据库上重现。所以我可能需要每个文件的每个字段。
鉴于文件的数量,手动和一个一个地处理所有文件是不可能的。
我只看到一个实用的解决方案来解决我的问题:应用 automatic programming。即编写一个程序,该程序将仅从一个来源生成程序:cobol copybooks。
我对允许使用的技术有一些限制(由客户设置)。我最终得到了一个 VB.NET 应用程序,它以 COBOL copybooks 作为输入,并且 :
- 生成 COBOL 程序,通过读取原始索引文件并将记录写入顺序文本文件,从而将数据转换成某些东西table。
- 生成 VBA 模块,其中包含将这些数据文件从 MS Access 导入 MySQL 所需的所有代码(包括 CREATE TABLE 和索引)
在项目开始时,我 运行 遇到了与您现在完全相同的问题,尤其是那些该死的重新定义。我发现列出和编码所有抄写可能性的任务,即使不是不可能,至少也是危险的。
所以我研究了另一种方式,发现了这个:
CB2XML
COBOL copybook 到 XML 转换器: SourceForge
这为我节省了数周的字帖解析和解释工作。
它可以解析 COBOL copybooks 以将它们更改为一个 XML 文件,它完美地描述了具有许多有用属性的所有 PICTURE,例如 length 或 type.它完全支持 COBOL'86 标准。
带有 Invoice 文件的示例(Facture 法语)
000001 FD FACTURE.
000006 01 REC-FACTURE.
000011 03 FS1 PIC X.
000016 03 FS2.
000021 05 FS2A PIC 9.
05 RFS2B PIC X(8).
000026 05 FS2B REDEFINES RFS2B PIC 9(8).
000031 03 FS3.
000036 05 FS3A PIC 9.
000041 05 FS3B PIC X(10).
000046 03 FS4.
000051 05 FS4A PIC 99.
000056 05 FS4B PIC 99.
000061 05 FS4C PIC 99.
000066 03 FS5 PIC X(5).
000071 03 FS6 PIC X(20).
000076 03 FS7 PIC 9.
000081 03 FS8 PIC S9(9)V99 COMP-3.
000086 03 FS9 PIC S9(9)V99 COMP-3.
000091 03 FS10 PIC 9.
000096 03 FS11 PIC S9(9)V99 COMP-3.
000101 03 FS12 PIC S9(9)V99 COMP-3.
000106 03 FS13 PIC S9(9)V99 COMP-3.
000111 03 FS14-15 OCCURS 10.
000116 05 FS14 PIC 9.
000121 05 FS15 PIC S9(9)V99 COMP-3.
000126 05 FS16 PIC S9(9)V99 COMP-3.
000131 03 FS17 OCCURS 10 PIC S9(9)V99 COMP-3.
000136 03 FS18 PIC 9(6).
000141 03 FS19 PIC 9.
000241 03 FILLER PIC X.
变成这样:
<copybook filename="FD8.COP.CLEAN">
<item display-length="428" level="01" name="REC-FACTURE" position="1" storage-length="428">
<item display-length="1" level="03" name="FS1" picture="X" position="1" storage-length="1"/>
<item display-length="9" level="03" name="FS2" position="2" storage-length="9">
<item display-length="1" level="05" name="FS2A" numeric="true" picture="9" position="2" storage-length="1"/>
<item display-length="8" level="05" name="RFS2B" picture="X(8)" position="3" redefined="true" storage-length="8"/>
<item display-length="8" level="05" name="FS2B" numeric="true" picture="9(8)" position="3" redefines="RFS2B" storage-length="8"/>
</item>
<item display-length="11" level="03" name="FS3" position="11" storage-length="11">
<item display-length="1" level="05" name="FS3A" numeric="true" picture="9" position="11" storage-length="1"/>
<item display-length="10" level="05" name="FS3B" picture="X(10)" position="12" storage-length="10"/>
</item>
<item display-length="6" level="03" name="FS4" position="22" storage-length="6">
<item display-length="2" level="05" name="FS4A" numeric="true" picture="99" position="22" storage-length="2"/>
<item display-length="2" level="05" name="FS4B" numeric="true" picture="99" position="24" storage-length="2"/>
<item display-length="2" level="05" name="FS4C" numeric="true" picture="99" position="26" storage-length="2"/>
</item>
<item display-length="5" level="03" name="FS5" picture="X(5)" position="28" storage-length="5"/>
<item display-length="20" level="03" name="FS6" picture="X(20)" position="33" storage-length="20"/>
<item display-length="1" level="03" name="FS7" numeric="true" picture="9" position="53" storage-length="1"/>
<item display-length="11" level="03" name="FS8" numeric="true" picture="S9(9)V99" position="54" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="03" name="FS9" numeric="true" picture="S9(9)V99" position="60" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="1" level="03" name="FS10" numeric="true" picture="9" position="66" storage-length="1"/>
<item display-length="11" level="03" name="FS11" numeric="true" picture="S9(9)V99" position="67" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="03" name="FS12" numeric="true" picture="S9(9)V99" position="73" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="03" name="FS13" numeric="true" picture="S9(9)V99" position="79" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="13" level="03" name="FS14-15" occurs="10" position="85" storage-length="13">
<item display-length="1" level="05" name="FS14" numeric="true" picture="9" position="85" storage-length="1"/>
<item display-length="11" level="05" name="FS15" numeric="true" picture="S9(9)V99" position="86" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="05" name="FS16" numeric="true" picture="S9(9)V99" position="92" scale="2" signed="true" storage-length="6" usage="computational-3"/>
</item>
<item display-length="11" level="03" name="FS17" numeric="true" occurs="10" picture="S9(9)V99" position="215" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="6" level="03" name="FS18" numeric="true" picture="9(6)" position="275" storage-length="6"/>
<item display-length="1" level="03" name="FS19" numeric="true" picture="9" position="281" storage-length="1"/>
所有 XML 属性的列表
我就偷懒这里copy/paste我的VB.NET代码,每个属性都有注释解释清楚
For Each Attribute As Xml.XmlAttribute In itemNode.Attributes
Select Case Attribute.Name
Case "name" ' FIeld name
Case "level" ' PICTURE level
Case "numeric" ' True if numeric data type
Case "picture" ' COmplete PICTURE string
Case "storage-length" ' Variable storage lenght
Case "usage" ' If COMP field, give the original COMP type ("computational-x")
Case "signed" ' true if PIC S...
Case "scale" ' Give number of digits afeter decimal point
Case "redefined" ' true if the field is redifined afterwards
Case "redefines" ' If REDEFINES : give the name of the redefined field
Case "occurs" ' give the number of occurences if it's an ARRAY
Case "position" ' Give the line position in the original copybook
Case "display-length" ' Give the display size
Case "filename" ' Give the FD name
在这个 XML 结构的帮助下,我已经实现了所有目标以及更多目标。
生成的 COBOL 程序,将 索引文件(只能用 RM cobol 运行time 读取)转换成 平面文件处理每个字段,包括 ARRAYS 和 REDEFINES。
- 对于 REDEFINES:我为 "primary" PICTURE 及其所有 REDEFINES 更改创建了一个字段,并且它们的类型匹配它们的 COBOL PICTURE
- 对于 ARRAY,我为每个元素创建一个字段,还创建一个包含整个数组的巨大字段 "line"
- 对于 COMPUTATIONAL 字段,我只是将原始 COMP 移动到完全相同的 DISPLAY PICTURE
并非所有字段在数据库中时都有用途,但至少所有内容始终可用
有了上面的发票文件,SEQUENTIAL 文本文件字帖就变成了这样:
自动生成 COBOL
FILE SECTION.
* -----------------------------------------------------------
* INPUT FILE
COPY "FD8.COP" .
* -----------------------------------------------------------
* OUTPUT FILE
FD FACTURE-DWH.
01 REC-FACTURE-DWH.
03 FS1-DWH PIC X.
03 FS2-DWH PIC X(9).
03 FS2A-DWH PIC 9.
03 RFS2B-DWH PIC X(8).
03 FS2B-DWH PIC 9(8).
03 FS3-DWH PIC X(11).
03 FS3A-DWH PIC 9.
03 FS3B-DWH PIC X(10).
03 FS4-DWH PIC X(6).
03 FS4A-DWH PIC 99.
03 FS4B-DWH PIC 99.
03 FS4C-DWH PIC 99.
03 FS5-DWH PIC X(5).
03 FS6-DWH PIC X(20).
03 FS7-DWH PIC 9.
03 FS8-DWH PIC -9(9)V99.
03 FS9-DWH PIC -9(9)V99.
03 FS10-DWH PIC 9.
03 FS11-DWH PIC -9(9)V99.
03 FS12-DWH PIC -9(9)V99.
03 FS13-DWH PIC -9(9)V99.
03 FS14-15-1-DWH PIC X(13).
03 FS14-15-2-DWH PIC X(13).
03 FS14-15-3-DWH PIC X(13).
03 FS14-15-4-DWH PIC X(13).
03 FS14-15-5-DWH PIC X(13).
03 FS14-15-6-DWH PIC X(13).
03 FS14-15-7-DWH PIC X(13).
03 FS14-15-8-DWH PIC X(13).
03 FS14-15-9-DWH PIC X(13).
03 FS14-15-10-DWH PIC X(13).
03 FS14-1-DWH PIC 9.
03 FS14-2-DWH PIC 9.
03 FS14-3-DWH PIC 9.
03 FS14-4-DWH PIC 9.
03 FS14-5-DWH PIC 9.
03 FS14-6-DWH PIC 9.
03 FS14-7-DWH PIC 9.
03 FS14-8-DWH PIC 9.
03 FS14-9-DWH PIC 9.
03 FS14-10-DWH PIC 9.
03 FS15-1-DWH PIC -9(9)V99.
03 FS15-2-DWH PIC -9(9)V99.
03 FS15-3-DWH PIC -9(9)V99.
03 FS15-4-DWH PIC -9(9)V99.
03 FS15-5-DWH PIC -9(9)V99.
03 FS15-6-DWH PIC -9(9)V99.
03 FS15-7-DWH PIC -9(9)V99.
03 FS15-8-DWH PIC -9(9)V99.
03 FS15-9-DWH PIC -9(9)V99.
03 FS15-10-DWH PIC -9(9)V99.
03 FS16-1-DWH PIC -9(9)V99.
03 FS16-2-DWH PIC -9(9)V99.
03 FS16-3-DWH PIC -9(9)V99.
03 FS16-4-DWH PIC -9(9)V99.
03 FS16-5-DWH PIC -9(9)V99.
03 FS16-6-DWH PIC -9(9)V99.
03 FS16-7-DWH PIC -9(9)V99.
03 FS16-8-DWH PIC -9(9)V99.
03 FS16-9-DWH PIC -9(9)V99.
03 FS16-10-DWH PIC -9(9)V99.
03 FS17-1-DWH PIC -9(9)V99.
03 FS17-2-DWH PIC -9(9)V99.
03 FS17-3-DWH PIC -9(9)V99.
03 FS17-4-DWH PIC -9(9)V99.
03 FS17-5-DWH PIC -9(9)V99.
03 FS17-6-DWH PIC -9(9)V99.
03 FS17-7-DWH PIC -9(9)V99.
03 FS17-8-DWH PIC -9(9)V99.
03 FS17-9-DWH PIC -9(9)V99.
03 FS17-10-DWH PIC -9(9)V99.
03 FS18-DWH PIC 9(6).
03 FS19-DWH PIC 9.
MOVE指令
* ============================================================
PROG.
MOVE FS1 TO FS1-DWH
MOVE FS2 TO FS2-DWH
MOVE FS2A TO FS2A-DWH
MOVE RFS2B TO RFS2B-DWH
MOVE FS2B TO FS2B-DWH
MOVE FS3 TO FS3-DWH
MOVE FS3A TO FS3A-DWH
MOVE FS3B TO FS3B-DWH
MOVE FS4 TO FS4-DWH
MOVE FS4A TO FS4A-DWH
MOVE FS4B TO FS4B-DWH
MOVE FS4C TO FS4C-DWH
MOVE FS5 TO FS5-DWH
MOVE FS6 TO FS6-DWH
MOVE FS7 TO FS7-DWH
MOVE FS8 TO FS8-DWH
MOVE FS9 TO FS9-DWH
MOVE FS10 TO FS10-DWH
MOVE FS11 TO FS11-DWH
MOVE FS12 TO FS12-DWH
MOVE FS13 TO FS13-DWH
MOVE FS14-15(1) TO FS14-15-1-DWH
MOVE FS14-15(2) TO FS14-15-2-DWH
MOVE FS14-15(3) TO FS14-15-3-DWH
MOVE FS14-15(4) TO FS14-15-4-DWH
MOVE FS14-15(5) TO FS14-15-5-DWH
MOVE FS14-15(6) TO FS14-15-6-DWH
MOVE FS14-15(7) TO FS14-15-7-DWH
MOVE FS14-15(8) TO FS14-15-8-DWH
MOVE FS14-15(9) TO FS14-15-9-DWH
MOVE FS14-15(10) TO FS14-15-10-DWH
MOVE FS14(1) TO FS14-1-DWH
MOVE FS14(2) TO FS14-2-DWH
MOVE FS14(3) TO FS14-3-DWH
MOVE FS14(4) TO FS14-4-DWH
MOVE FS14(5) TO FS14-5-DWH
MOVE FS14(6) TO FS14-6-DWH
MOVE FS14(7) TO FS14-7-DWH
MOVE FS14(8) TO FS14-8-DWH
MOVE FS14(9) TO FS14-9-DWH
MOVE FS14(10) TO FS14-10-DWH
MOVE FS15(1) TO FS15-1-DWH
MOVE FS15(2) TO FS15-2-DWH
MOVE FS15(3) TO FS15-3-DWH
MOVE FS15(4) TO FS15-4-DWH
MOVE FS15(5) TO FS15-5-DWH
MOVE FS15(6) TO FS15-6-DWH
MOVE FS15(7) TO FS15-7-DWH
MOVE FS15(8) TO FS15-8-DWH
MOVE FS15(9) TO FS15-9-DWH
MOVE FS15(10) TO FS15-10-DWH
MOVE FS16(1) TO FS16-1-DWH
MOVE FS16(2) TO FS16-2-DWH
MOVE FS16(3) TO FS16-3-DWH
MOVE FS16(4) TO FS16-4-DWH
MOVE FS16(5) TO FS16-5-DWH
MOVE FS16(6) TO FS16-6-DWH
MOVE FS16(7) TO FS16-7-DWH
MOVE FS16(8) TO FS16-8-DWH
MOVE FS16(9) TO FS16-9-DWH
MOVE FS16(10) TO FS16-10-DWH
MOVE FS17(1) TO FS17-1-DWH
MOVE FS17(2) TO FS17-2-DWH
MOVE FS17(3) TO FS17-3-DWH
MOVE FS17(4) TO FS17-4-DWH
MOVE FS17(5) TO FS17-5-DWH
MOVE FS17(6) TO FS17-6-DWH
MOVE FS17(7) TO FS17-7-DWH
MOVE FS17(8) TO FS17-8-DWH
MOVE FS17(9) TO FS17-9-DWH
MOVE FS17(10) TO FS17-10-DWH
MOVE FS18 TO FS18-DWH
MOVE FS19 TO FS19-DWH
写入平面文件后,可以通过 VBA 代码将它们处理为 MySQL,也由 VB.NET 应用程序生成。
自动生成VBA
键入def声明处理文本文件输入
在每个字段旁边的评论中注意原始图片
'-------------------------------------------------------------
' REC_FC8 Record
'-------------------------------------------------------------
Private Type REC_FC8
FS1 as string*1 ' 03 FS1 PIC X
FS2 as string*9 ' 03 FS2 PIC
FS2A as string*1 ' 05 FS2A PIC 9
RFS2B as string*8 ' 05 RFS2B PIC X(8)
FS2B as string*8 ' 05 FS2B PIC 9(8)
FS3 as string*11 ' 03 FS3 PIC
FS3A as string*1 ' 05 FS3A PIC 9
FS3B as string*10 ' 05 FS3B PIC X(10)
FS4 as string*6 ' 03 FS4 PIC
FS4A as string*2 ' 05 FS4A PIC 99
FS4B as string*2 ' 05 FS4B PIC 99
FS4C as string*2 ' 05 FS4C PIC 99
FS5 as string*5 ' 03 FS5 PIC X(5)
FS6 as string*20 ' 03 FS6 PIC X(20)
FS7 as string*1 ' 03 FS7 PIC 9
FS8 as string*12 ' 03 FS8 PIC S9(9)V99 computational-3
FS9 as string*12 ' 03 FS9 PIC S9(9)V99 computational-3
FS10 as string*1 ' 03 FS10 PIC 9
FS11 as string*12 ' 03 FS11 PIC S9(9)V99 computational-3
FS12 as string*12 ' 03 FS12 PIC S9(9)V99 computational-3
FS13 as string*12 ' 03 FS13 PIC S9(9)V99 computational-3
FS14_15_1 as string*13 ' 03 FS14-15 PIC
FS14_15_2 as string*13 ' 03 FS14-15 PIC
FS14_15_3 as string*13 ' 03 FS14-15 PIC
FS14_15_4 as string*13 ' 03 FS14-15 PIC
FS14_15_5 as string*13 ' 03 FS14-15 PIC
FS14_15_6 as string*13 ' 03 FS14-15 PIC
FS14_15_7 as string*13 ' 03 FS14-15 PIC
FS14_15_8 as string*13 ' 03 FS14-15 PIC
FS14_15_9 as string*13 ' 03 FS14-15 PIC
FS14_15_10 as string*13 ' 03 FS14-15 PIC
FS14_1 as string*1 ' 05 FS14 PIC 9
FS14_2 as string*1 ' 05 FS14 PIC 9
FS14_3 as string*1 ' 05 FS14 PIC 9
FS14_4 as string*1 ' 05 FS14 PIC 9
FS14_5 as string*1 ' 05 FS14 PIC 9
FS14_6 as string*1 ' 05 FS14 PIC 9
FS14_7 as string*1 ' 05 FS14 PIC 9
FS14_8 as string*1 ' 05 FS14 PIC 9
FS14_9 as string*1 ' 05 FS14 PIC 9
FS14_10 as string*1 ' 05 FS14 PIC 9
FS15_1 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_2 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_3 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_4 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_5 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_6 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_7 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_8 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
...
FS17_8 as string*12 ' 03 FS17 PIC S9(9)V99 computational-3
FS17_9 as string*12 ' 03 FS17 PIC S9(9)V99 computational-3
FS17_10 as string*12 ' 03 FS17 PIC S9(9)V99 computational-3
FS18 as string*6 ' 03 FS18 PIC 9(6)
FS19 as string*1 ' 03 FS19 PIC 9
FC8LF As String * 2 ' LF 11
End Type
创建 table 过程
每个字段都变成了一个对象(来自我创建的自定义 class),SQLtypeFull
在每个字段的 returns MySQL 数据类型下面使用了方法 SQLtypeFull
=21=]
'========================================================================
Private Function Create_Table_MySQL() As Boolean
On Error GoTo Erreur
Dim Rs As Recordset
Dim SQL As String
SQL = "CREATE TABLE IF NOT EXISTS `TBL_DAT_FACTURE` ( `ID` INT(11) NOT NULL auto_increment, `RECID` INT(11)"
SQL = SQL & ", `FS1` " & FS1.SQLtypeFull
SQL = SQL & ", `FS2` " & FS2.SQLtypeFull
SQL = SQL & ", `FS2A` " & FS2A.SQLtypeFull
SQL = SQL & ", `RFS2B` " & RFS2B.SQLtypeFull
SQL = SQL & ", `FS2B` " & FS2B.SQLtypeFull
SQL = SQL & ", `FS3` " & FS3.SQLtypeFull
SQL = SQL & ", `FS3A` " & FS3A.SQLtypeFull
SQL = SQL & ", `FS3B` " & FS3B.SQLtypeFull
SQL = SQL & ", `FS4` " & FS4.SQLtypeFull
SQL = SQL & ", `FS4A` " & FS4A.SQLtypeFull
SQL = SQL & ", `FS4B` " & FS4B.SQLtypeFull
SQL = SQL & ", `FS4C` " & FS4C.SQLtypeFull
SQL = SQL & ", `FS5` " & FS5.SQLtypeFull
SQL = SQL & ", `FS6` " & FS6.SQLtypeFull
SQL = SQL & ", `FS7` " & FS7.SQLtypeFull
SQL = SQL & ", `FS8` " & FS8.SQLtypeFull
SQL = SQL & ", `FS9` " & FS9.SQLtypeFull
SQL = SQL & ", `FS10` " & FS10.SQLtypeFull
SQL = SQL & ", `FS11` " & FS11.SQLtypeFull
SQL = SQL & ", `FS12` " & FS12.SQLtypeFull
SQL = SQL & ", `FS13` " & FS13.SQLtypeFull
SQL = SQL & ", `FS14_15_1` " & FS14_15_1.SQLtypeFull
SQL = SQL & ", `FS14_15_2` " & FS14_15_2.SQLtypeFull
SQL = SQL & ", `FS14_15_3` " & FS14_15_3.SQLtypeFull
SQL = SQL & ", `FS14_15_4` " & FS14_15_4.SQLtypeFull
SQL = SQL & ", `FS14_15_5` " & FS14_15_5.SQLtypeFull
SQL = SQL & ", `FS14_15_6` " & FS14_15_6.SQLtypeFull
SQL = SQL & ", `FS14_15_7` " & FS14_15_7.SQLtypeFull
SQL = SQL & ", `FS14_15_8` " & FS14_15_8.SQLtypeFull
SQL = SQL & ", `FS14_15_9` " & FS14_15_9.SQLtypeFull
SQL = SQL & ", `FS14_15_10` " & FS14_15_10.SQLtypeFull
SQL = SQL & ", `FS14_1` " & FS14_1.SQLtypeFull
SQL = SQL & ", `FS14_2` " & FS14_2.SQLtypeFull
SQL = SQL & ", `FS14_3` " & FS14_3.SQLtypeFull
SQL = SQL & ", `FS14_4` " & FS14_4.SQLtypeFull
SQL = SQL & ", `FS14_5` " & FS14_5.SQLtypeFull
SQL = SQL & ", `FS14_6` " & FS14_6.SQLtypeFull
SQL = SQL & ", `FS14_7` " & FS14_7.SQLtypeFull
SQL = SQL & ", `FS14_8` " & FS14_8.SQLtypeFull
SQL = SQL & ", `FS14_9` " & FS14_9.SQLtypeFull
SQL = SQL & ", `FS14_10` " & FS14_10.SQLtypeFull
SQL = SQL & ", `FS15_1` " & FS15_1.SQLtypeFull
SQL = SQL & ", `FS15_2` " & FS15_2.SQLtypeFull
SQL = SQL & ", `FS15_3` " & FS15_3.SQLtypeFull
SQL = SQL & ", `FS15_4` " & FS15_4.SQLtypeFull
SQL = SQL & ", `FS15_5` " & FS15_5.SQLtypeFull
...
SQL = SQL & ", `FS17_9` " & FS17_9.SQLtypeFull
SQL = SQL & ", `FS17_10` " & FS17_10.SQLtypeFull
SQL = SQL & ", `FS18` " & FS18.SQLtypeFull
SQL = SQL & ", `FS19` " & FS19.SQLtypeFull
SQL = SQL & ", PRIMARY KEY (`ID`)"
SQL = SQL & ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_bin;"
MySQLcon.Execute (SQL)
Create_Table_MySQL = True
Exit_Sub:
Exit Function
Erreur:
Create_Table_MySQL = False
Resume Exit_Sub
End Function
最终SQL声明
CREATE TABLE IF NOT EXISTS `FACTURE`
( `ID` INT(11) NOT NULL auto_increment, `RECID` INT(11), `FS1` CHAR(1), `FS2` CHAR(9), `FS2A` TINYINT(1) UNSIGNED, `RFS2B` CHAR(8), `FS2B` INT(8) UNSIGNED, `FS3` CHAR(11), `FS3A` TINYINT(1) UNSIGNED, `FS3B` CHAR(10), `FS4` CHAR(6), `FS4A` TINYINT(2) UNSIGNED, `FS4B` TINYINT(2) UNSIGNED, `FS4C` TINYINT(2) UNSIGNED, `FS5` CHAR(5), `FS6` CHAR(20), `FS7` TINYINT(1) UNSIGNED, `FS8` DECIMAL(11,2), `FS9` DECIMAL(11,2), `FS10` TINYINT(1) UNSIGNED, `FS11` DECIMAL(11,2), `FS12` DECIMAL(11,2), `FS13` DECIMAL(11,2), `FS14_15_1` CHAR(13), `FS14_15_2` CHAR(13), `FS14_15_3` CHAR(13), `FS14_15_4` CHAR(13), `FS14_15_5` CHAR(13), `FS14_15_6` CHAR(13), `FS14_15_7` CHAR(13), `FS14_15_8` CHAR(13), `FS14_15_9` CHAR(13), `FS14_15_10` CHAR(13), `FS14_1` TINYINT(1) UNSIGNED, `FS14_2` TINYINT(1) UNSIGNED, `FS14_3` TINYINT(1) UNSIGNED, `FS14_4` TINYINT(1) UNSIGNED, `FS14_5` TINYINT(1) UNSIGNED, `FS14_6` TINYINT(1) UNSIGNED, `FS14_7` TINYINT(1) UNSIGNED, `FS14_8` TINYINT(1) UNSIGNED, `FS14_9` TINYIN
T(1) UNSIGNED, `FS14_10` TINYINT(1) UNSIGNED, `FS15_1` DECIMAL(11,2), `FS15_2` DECIMAL(11,2), `FS15_3` DECIMAL(11,2), `FS15_4` DECIMAL(11,2), `FS15_5` DECIMAL(11,2), `FS15_6` DECIMAL(11,2), `FS15_7` DECIMAL(11,2), `FS15_8`
...
DECIMAL(11,2), `FS17_10` DECIMAL(11,2), `FS18` DATE, `FS19` TINYINT(1) UNSIGNED,
PRIMARY KEY (`ID`)) ENGINE=MyISAM
DEFAULT CHARSET=utf8 COLLATE utf8_bin;
我在生成的 VBA 模块中有更多内容,生成的 xml 的详细程度和准确性对所有模块都有很大帮助:
- 我创建了一个 Class 来管理字段的所有方面,特别是处理原始 PICTURE 和 VBA 类型(日期、长、双精度)后的转换 VBA/MySQL , currency, etc...) 还有一个挂钩,以防你想强制使用另一种类型。
- 它完全处理元数据创建(也在 MySQL 中)
- 它处理导入数据时的错误,在文件和字段级别记录所有内容
我可能已经展示了足够多的东西给你一些想法,所以我就到此为止了。
最重要的:当我们运行将在 COBOL ERP 中进行的复杂计算放入 SQL 语句时 运行在新的数据仓库中,数据库返回的数字与 ERP 中的数字完全相同。在数百万条记录上,计算中没有一位数字的损失。这是证明它有效的最好方法:-)
如果您想知道为什么我使用 Access/VBA 而不是 .NET 进行导入:这是一个没有商量余地的要求。
最后一点:我与 CB2XML 没有任何关联,这不是它的广告。这是一款非常有用的软件,值得关注。
我正在制作一个 C# 程序,它将能够动态读取用 COBOL 编写的 IBM HOST Copybook 并从中生成 SQL table。生成 table 后,我可以将文件上传到我的程序中,它将读取、从 IMB-37 转换并将文件插入 sql table。到目前为止,我几乎可以处理任何事情,尽管我 运行 遇到了 REDEFINES 的一些问题。
例如:
10 SOME-FIELD PIC 9(3) COMP-3. SCRRB205
4117 10 SOME-OTHER-FIELD REDEFINES 3041-17
4117 SOME-FIELD PIC X(2). 3041-17
我知道在这种情况下,重新定义取代了它上面的字段,尽管我不明白的是编译器如何知道它是否应该在其上使用重新定义。我假设在这种情况下是因为第一个是数字而第二个是字符,尽管在下面的示例中它们都使用字符。
05 STREET-ADDRESS.
10 ADDRESS-LINE-1 PIC X(20).
10 ADDRESS-LINE-2 PIC X(20).
05 PO-BOX REDEFINES STREET-ADDRESS PIC X(40).
我试过忽略重新定义,因为它总是需要相同数量的 space,但是在原始字段被打包而重新定义的字段没有打包的情况下,我需要知道何时解包领域。
任何对此的帮助都会很棒!
REDEFINES
将使您的任务更加困难。并不是 "compiler" 知道要使用哪个特定字段,直观上,是现有 COBOL 系统中的代码知道要使用哪个字段。会有一些指示,在另一个字段中有一些值,这将指示在特定时间使用哪些字段。
以你的第二个例子为例,因为第一个例子缺乏上下文:
05 ADDRESS-PO-BOX-FLAG PIC X.
在使用数据之前将询问该字段。直接(您可以在那里找到很多可怕的代码)或使用 88 级条件名称:
88 ADDRESS-IS-A-PO-BOX VALUE "Y". (an example only)
IF ADDRESS-IS-A-PO-BOX
some code relating to PO Boxes
ELSE
some code relating to other types of addresses
END-IF
您的第一个示例将以类似的方式处理。
REDEFINES 的 "old style" 用法,在互斥情况下使用记录上的相同存储位置。节省昂贵的存储空间。您正在使用的系统要么是 "old",要么是它的设计被错误的 "experience".
感染了您有两个广泛的选择:复制所有条件选择的数据(以便您有两组业务逻辑保持同步);更改文件,以便每个字段占用自己的存储空间。
COMP-3(或 PACKED-DECIMAL)或 COMP/COMP-4/COMP-5/BINARY 数据类型的存在也会使您的事情复杂化。然后,您需要在字段级别为实际的 EBCDIC 数据执行 EBCDIC 到 ASCII 的操作,并执行任何必要的操作来转换或简单地获取 "computational" 数据。
另请注意,任何带符号的显示数字字段(带有以 S 开头但没有明确 "computational" 用法的 PICture 的数字字段)显然会在最后一个字节中包含 "character" 数据,因为符号被保存为最后一个字节的 "overpunch"。
请注意,二进制数据类型将是 Big Endian。
如果您收到没有 REDEFINES、没有 "computational" 字段且没有嵌入符号(或隐含的小数位)的文件,对您来说会简单得多。您的所有数据都是字符,您可以在记录级别(或在文件级别,使用您的文件传输机制)从 EBCDIC 到 ASCII。
如果您在此处查看标记为 COMP-3 的问题,您会找到对此的进一步讨论,并且如果您决定荒谬的路线(您的程序理解本机大型机 COBOL 数据项而不是普通 "text") 是唯一可行的方法,那么讨论中有许多内容您可能会觉得有用并且能够使用或应用。
如果您的公司是 "regulated" 外部的,那么在编写一行代码之前,请确保您的合规、审计和会计部门对您的设计感到满意。哎呀。迟到了。让我们希望它是制造业。
也许我可以帮助你,因为 2 年前我已经完成了你现在正在做的事情。
我不得不设计一个 MySQL 数据仓库,包括 ETL 系统,完全基于来自 RM COBOL ERP 应用程序 运行 的文件 运行 =150=]。 该应用程序有 600 多个文件,目前还不清楚其中有多少文件最终会进入数据库。大多数重要文件都在 COMP 字段上建立了索引,以使其更难,其中一个明显的要求是文件及其索引键之间的所有关系都可以在数据库上重现。所以我可能需要每个文件的每个字段。
鉴于文件的数量,手动和一个一个地处理所有文件是不可能的。
我只看到一个实用的解决方案来解决我的问题:应用 automatic programming。即编写一个程序,该程序将仅从一个来源生成程序:cobol copybooks。
我对允许使用的技术有一些限制(由客户设置)。我最终得到了一个 VB.NET 应用程序,它以 COBOL copybooks 作为输入,并且 :
- 生成 COBOL 程序,通过读取原始索引文件并将记录写入顺序文本文件,从而将数据转换成某些东西table。
- 生成 VBA 模块,其中包含将这些数据文件从 MS Access 导入 MySQL 所需的所有代码(包括 CREATE TABLE 和索引)
在项目开始时,我 运行 遇到了与您现在完全相同的问题,尤其是那些该死的重新定义。我发现列出和编码所有抄写可能性的任务,即使不是不可能,至少也是危险的。 所以我研究了另一种方式,发现了这个:
CB2XML
COBOL copybook 到 XML 转换器: SourceForge
这为我节省了数周的字帖解析和解释工作。 它可以解析 COBOL copybooks 以将它们更改为一个 XML 文件,它完美地描述了具有许多有用属性的所有 PICTURE,例如 length 或 type.它完全支持 COBOL'86 标准。
带有 Invoice 文件的示例(Facture 法语)
000001 FD FACTURE.
000006 01 REC-FACTURE.
000011 03 FS1 PIC X.
000016 03 FS2.
000021 05 FS2A PIC 9.
05 RFS2B PIC X(8).
000026 05 FS2B REDEFINES RFS2B PIC 9(8).
000031 03 FS3.
000036 05 FS3A PIC 9.
000041 05 FS3B PIC X(10).
000046 03 FS4.
000051 05 FS4A PIC 99.
000056 05 FS4B PIC 99.
000061 05 FS4C PIC 99.
000066 03 FS5 PIC X(5).
000071 03 FS6 PIC X(20).
000076 03 FS7 PIC 9.
000081 03 FS8 PIC S9(9)V99 COMP-3.
000086 03 FS9 PIC S9(9)V99 COMP-3.
000091 03 FS10 PIC 9.
000096 03 FS11 PIC S9(9)V99 COMP-3.
000101 03 FS12 PIC S9(9)V99 COMP-3.
000106 03 FS13 PIC S9(9)V99 COMP-3.
000111 03 FS14-15 OCCURS 10.
000116 05 FS14 PIC 9.
000121 05 FS15 PIC S9(9)V99 COMP-3.
000126 05 FS16 PIC S9(9)V99 COMP-3.
000131 03 FS17 OCCURS 10 PIC S9(9)V99 COMP-3.
000136 03 FS18 PIC 9(6).
000141 03 FS19 PIC 9.
000241 03 FILLER PIC X.
变成这样:
<copybook filename="FD8.COP.CLEAN">
<item display-length="428" level="01" name="REC-FACTURE" position="1" storage-length="428">
<item display-length="1" level="03" name="FS1" picture="X" position="1" storage-length="1"/>
<item display-length="9" level="03" name="FS2" position="2" storage-length="9">
<item display-length="1" level="05" name="FS2A" numeric="true" picture="9" position="2" storage-length="1"/>
<item display-length="8" level="05" name="RFS2B" picture="X(8)" position="3" redefined="true" storage-length="8"/>
<item display-length="8" level="05" name="FS2B" numeric="true" picture="9(8)" position="3" redefines="RFS2B" storage-length="8"/>
</item>
<item display-length="11" level="03" name="FS3" position="11" storage-length="11">
<item display-length="1" level="05" name="FS3A" numeric="true" picture="9" position="11" storage-length="1"/>
<item display-length="10" level="05" name="FS3B" picture="X(10)" position="12" storage-length="10"/>
</item>
<item display-length="6" level="03" name="FS4" position="22" storage-length="6">
<item display-length="2" level="05" name="FS4A" numeric="true" picture="99" position="22" storage-length="2"/>
<item display-length="2" level="05" name="FS4B" numeric="true" picture="99" position="24" storage-length="2"/>
<item display-length="2" level="05" name="FS4C" numeric="true" picture="99" position="26" storage-length="2"/>
</item>
<item display-length="5" level="03" name="FS5" picture="X(5)" position="28" storage-length="5"/>
<item display-length="20" level="03" name="FS6" picture="X(20)" position="33" storage-length="20"/>
<item display-length="1" level="03" name="FS7" numeric="true" picture="9" position="53" storage-length="1"/>
<item display-length="11" level="03" name="FS8" numeric="true" picture="S9(9)V99" position="54" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="03" name="FS9" numeric="true" picture="S9(9)V99" position="60" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="1" level="03" name="FS10" numeric="true" picture="9" position="66" storage-length="1"/>
<item display-length="11" level="03" name="FS11" numeric="true" picture="S9(9)V99" position="67" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="03" name="FS12" numeric="true" picture="S9(9)V99" position="73" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="03" name="FS13" numeric="true" picture="S9(9)V99" position="79" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="13" level="03" name="FS14-15" occurs="10" position="85" storage-length="13">
<item display-length="1" level="05" name="FS14" numeric="true" picture="9" position="85" storage-length="1"/>
<item display-length="11" level="05" name="FS15" numeric="true" picture="S9(9)V99" position="86" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="11" level="05" name="FS16" numeric="true" picture="S9(9)V99" position="92" scale="2" signed="true" storage-length="6" usage="computational-3"/>
</item>
<item display-length="11" level="03" name="FS17" numeric="true" occurs="10" picture="S9(9)V99" position="215" scale="2" signed="true" storage-length="6" usage="computational-3"/>
<item display-length="6" level="03" name="FS18" numeric="true" picture="9(6)" position="275" storage-length="6"/>
<item display-length="1" level="03" name="FS19" numeric="true" picture="9" position="281" storage-length="1"/>
所有 XML 属性的列表
我就偷懒这里copy/paste我的VB.NET代码,每个属性都有注释解释清楚
For Each Attribute As Xml.XmlAttribute In itemNode.Attributes
Select Case Attribute.Name
Case "name" ' FIeld name
Case "level" ' PICTURE level
Case "numeric" ' True if numeric data type
Case "picture" ' COmplete PICTURE string
Case "storage-length" ' Variable storage lenght
Case "usage" ' If COMP field, give the original COMP type ("computational-x")
Case "signed" ' true if PIC S...
Case "scale" ' Give number of digits afeter decimal point
Case "redefined" ' true if the field is redifined afterwards
Case "redefines" ' If REDEFINES : give the name of the redefined field
Case "occurs" ' give the number of occurences if it's an ARRAY
Case "position" ' Give the line position in the original copybook
Case "display-length" ' Give the display size
Case "filename" ' Give the FD name
在这个 XML 结构的帮助下,我已经实现了所有目标以及更多目标。
生成的 COBOL 程序,将 索引文件(只能用 RM cobol 运行time 读取)转换成 平面文件处理每个字段,包括 ARRAYS 和 REDEFINES。
- 对于 REDEFINES:我为 "primary" PICTURE 及其所有 REDEFINES 更改创建了一个字段,并且它们的类型匹配它们的 COBOL PICTURE
- 对于 ARRAY,我为每个元素创建一个字段,还创建一个包含整个数组的巨大字段 "line"
- 对于 COMPUTATIONAL 字段,我只是将原始 COMP 移动到完全相同的 DISPLAY PICTURE
并非所有字段在数据库中时都有用途,但至少所有内容始终可用
有了上面的发票文件,SEQUENTIAL 文本文件字帖就变成了这样:
自动生成 COBOL
FILE SECTION.
* -----------------------------------------------------------
* INPUT FILE
COPY "FD8.COP" .
* -----------------------------------------------------------
* OUTPUT FILE
FD FACTURE-DWH.
01 REC-FACTURE-DWH.
03 FS1-DWH PIC X.
03 FS2-DWH PIC X(9).
03 FS2A-DWH PIC 9.
03 RFS2B-DWH PIC X(8).
03 FS2B-DWH PIC 9(8).
03 FS3-DWH PIC X(11).
03 FS3A-DWH PIC 9.
03 FS3B-DWH PIC X(10).
03 FS4-DWH PIC X(6).
03 FS4A-DWH PIC 99.
03 FS4B-DWH PIC 99.
03 FS4C-DWH PIC 99.
03 FS5-DWH PIC X(5).
03 FS6-DWH PIC X(20).
03 FS7-DWH PIC 9.
03 FS8-DWH PIC -9(9)V99.
03 FS9-DWH PIC -9(9)V99.
03 FS10-DWH PIC 9.
03 FS11-DWH PIC -9(9)V99.
03 FS12-DWH PIC -9(9)V99.
03 FS13-DWH PIC -9(9)V99.
03 FS14-15-1-DWH PIC X(13).
03 FS14-15-2-DWH PIC X(13).
03 FS14-15-3-DWH PIC X(13).
03 FS14-15-4-DWH PIC X(13).
03 FS14-15-5-DWH PIC X(13).
03 FS14-15-6-DWH PIC X(13).
03 FS14-15-7-DWH PIC X(13).
03 FS14-15-8-DWH PIC X(13).
03 FS14-15-9-DWH PIC X(13).
03 FS14-15-10-DWH PIC X(13).
03 FS14-1-DWH PIC 9.
03 FS14-2-DWH PIC 9.
03 FS14-3-DWH PIC 9.
03 FS14-4-DWH PIC 9.
03 FS14-5-DWH PIC 9.
03 FS14-6-DWH PIC 9.
03 FS14-7-DWH PIC 9.
03 FS14-8-DWH PIC 9.
03 FS14-9-DWH PIC 9.
03 FS14-10-DWH PIC 9.
03 FS15-1-DWH PIC -9(9)V99.
03 FS15-2-DWH PIC -9(9)V99.
03 FS15-3-DWH PIC -9(9)V99.
03 FS15-4-DWH PIC -9(9)V99.
03 FS15-5-DWH PIC -9(9)V99.
03 FS15-6-DWH PIC -9(9)V99.
03 FS15-7-DWH PIC -9(9)V99.
03 FS15-8-DWH PIC -9(9)V99.
03 FS15-9-DWH PIC -9(9)V99.
03 FS15-10-DWH PIC -9(9)V99.
03 FS16-1-DWH PIC -9(9)V99.
03 FS16-2-DWH PIC -9(9)V99.
03 FS16-3-DWH PIC -9(9)V99.
03 FS16-4-DWH PIC -9(9)V99.
03 FS16-5-DWH PIC -9(9)V99.
03 FS16-6-DWH PIC -9(9)V99.
03 FS16-7-DWH PIC -9(9)V99.
03 FS16-8-DWH PIC -9(9)V99.
03 FS16-9-DWH PIC -9(9)V99.
03 FS16-10-DWH PIC -9(9)V99.
03 FS17-1-DWH PIC -9(9)V99.
03 FS17-2-DWH PIC -9(9)V99.
03 FS17-3-DWH PIC -9(9)V99.
03 FS17-4-DWH PIC -9(9)V99.
03 FS17-5-DWH PIC -9(9)V99.
03 FS17-6-DWH PIC -9(9)V99.
03 FS17-7-DWH PIC -9(9)V99.
03 FS17-8-DWH PIC -9(9)V99.
03 FS17-9-DWH PIC -9(9)V99.
03 FS17-10-DWH PIC -9(9)V99.
03 FS18-DWH PIC 9(6).
03 FS19-DWH PIC 9.
MOVE指令
* ============================================================
PROG.
MOVE FS1 TO FS1-DWH
MOVE FS2 TO FS2-DWH
MOVE FS2A TO FS2A-DWH
MOVE RFS2B TO RFS2B-DWH
MOVE FS2B TO FS2B-DWH
MOVE FS3 TO FS3-DWH
MOVE FS3A TO FS3A-DWH
MOVE FS3B TO FS3B-DWH
MOVE FS4 TO FS4-DWH
MOVE FS4A TO FS4A-DWH
MOVE FS4B TO FS4B-DWH
MOVE FS4C TO FS4C-DWH
MOVE FS5 TO FS5-DWH
MOVE FS6 TO FS6-DWH
MOVE FS7 TO FS7-DWH
MOVE FS8 TO FS8-DWH
MOVE FS9 TO FS9-DWH
MOVE FS10 TO FS10-DWH
MOVE FS11 TO FS11-DWH
MOVE FS12 TO FS12-DWH
MOVE FS13 TO FS13-DWH
MOVE FS14-15(1) TO FS14-15-1-DWH
MOVE FS14-15(2) TO FS14-15-2-DWH
MOVE FS14-15(3) TO FS14-15-3-DWH
MOVE FS14-15(4) TO FS14-15-4-DWH
MOVE FS14-15(5) TO FS14-15-5-DWH
MOVE FS14-15(6) TO FS14-15-6-DWH
MOVE FS14-15(7) TO FS14-15-7-DWH
MOVE FS14-15(8) TO FS14-15-8-DWH
MOVE FS14-15(9) TO FS14-15-9-DWH
MOVE FS14-15(10) TO FS14-15-10-DWH
MOVE FS14(1) TO FS14-1-DWH
MOVE FS14(2) TO FS14-2-DWH
MOVE FS14(3) TO FS14-3-DWH
MOVE FS14(4) TO FS14-4-DWH
MOVE FS14(5) TO FS14-5-DWH
MOVE FS14(6) TO FS14-6-DWH
MOVE FS14(7) TO FS14-7-DWH
MOVE FS14(8) TO FS14-8-DWH
MOVE FS14(9) TO FS14-9-DWH
MOVE FS14(10) TO FS14-10-DWH
MOVE FS15(1) TO FS15-1-DWH
MOVE FS15(2) TO FS15-2-DWH
MOVE FS15(3) TO FS15-3-DWH
MOVE FS15(4) TO FS15-4-DWH
MOVE FS15(5) TO FS15-5-DWH
MOVE FS15(6) TO FS15-6-DWH
MOVE FS15(7) TO FS15-7-DWH
MOVE FS15(8) TO FS15-8-DWH
MOVE FS15(9) TO FS15-9-DWH
MOVE FS15(10) TO FS15-10-DWH
MOVE FS16(1) TO FS16-1-DWH
MOVE FS16(2) TO FS16-2-DWH
MOVE FS16(3) TO FS16-3-DWH
MOVE FS16(4) TO FS16-4-DWH
MOVE FS16(5) TO FS16-5-DWH
MOVE FS16(6) TO FS16-6-DWH
MOVE FS16(7) TO FS16-7-DWH
MOVE FS16(8) TO FS16-8-DWH
MOVE FS16(9) TO FS16-9-DWH
MOVE FS16(10) TO FS16-10-DWH
MOVE FS17(1) TO FS17-1-DWH
MOVE FS17(2) TO FS17-2-DWH
MOVE FS17(3) TO FS17-3-DWH
MOVE FS17(4) TO FS17-4-DWH
MOVE FS17(5) TO FS17-5-DWH
MOVE FS17(6) TO FS17-6-DWH
MOVE FS17(7) TO FS17-7-DWH
MOVE FS17(8) TO FS17-8-DWH
MOVE FS17(9) TO FS17-9-DWH
MOVE FS17(10) TO FS17-10-DWH
MOVE FS18 TO FS18-DWH
MOVE FS19 TO FS19-DWH
写入平面文件后,可以通过 VBA 代码将它们处理为 MySQL,也由 VB.NET 应用程序生成。
自动生成VBA
键入def声明处理文本文件输入
在每个字段旁边的评论中注意原始图片
'-------------------------------------------------------------
' REC_FC8 Record
'-------------------------------------------------------------
Private Type REC_FC8
FS1 as string*1 ' 03 FS1 PIC X
FS2 as string*9 ' 03 FS2 PIC
FS2A as string*1 ' 05 FS2A PIC 9
RFS2B as string*8 ' 05 RFS2B PIC X(8)
FS2B as string*8 ' 05 FS2B PIC 9(8)
FS3 as string*11 ' 03 FS3 PIC
FS3A as string*1 ' 05 FS3A PIC 9
FS3B as string*10 ' 05 FS3B PIC X(10)
FS4 as string*6 ' 03 FS4 PIC
FS4A as string*2 ' 05 FS4A PIC 99
FS4B as string*2 ' 05 FS4B PIC 99
FS4C as string*2 ' 05 FS4C PIC 99
FS5 as string*5 ' 03 FS5 PIC X(5)
FS6 as string*20 ' 03 FS6 PIC X(20)
FS7 as string*1 ' 03 FS7 PIC 9
FS8 as string*12 ' 03 FS8 PIC S9(9)V99 computational-3
FS9 as string*12 ' 03 FS9 PIC S9(9)V99 computational-3
FS10 as string*1 ' 03 FS10 PIC 9
FS11 as string*12 ' 03 FS11 PIC S9(9)V99 computational-3
FS12 as string*12 ' 03 FS12 PIC S9(9)V99 computational-3
FS13 as string*12 ' 03 FS13 PIC S9(9)V99 computational-3
FS14_15_1 as string*13 ' 03 FS14-15 PIC
FS14_15_2 as string*13 ' 03 FS14-15 PIC
FS14_15_3 as string*13 ' 03 FS14-15 PIC
FS14_15_4 as string*13 ' 03 FS14-15 PIC
FS14_15_5 as string*13 ' 03 FS14-15 PIC
FS14_15_6 as string*13 ' 03 FS14-15 PIC
FS14_15_7 as string*13 ' 03 FS14-15 PIC
FS14_15_8 as string*13 ' 03 FS14-15 PIC
FS14_15_9 as string*13 ' 03 FS14-15 PIC
FS14_15_10 as string*13 ' 03 FS14-15 PIC
FS14_1 as string*1 ' 05 FS14 PIC 9
FS14_2 as string*1 ' 05 FS14 PIC 9
FS14_3 as string*1 ' 05 FS14 PIC 9
FS14_4 as string*1 ' 05 FS14 PIC 9
FS14_5 as string*1 ' 05 FS14 PIC 9
FS14_6 as string*1 ' 05 FS14 PIC 9
FS14_7 as string*1 ' 05 FS14 PIC 9
FS14_8 as string*1 ' 05 FS14 PIC 9
FS14_9 as string*1 ' 05 FS14 PIC 9
FS14_10 as string*1 ' 05 FS14 PIC 9
FS15_1 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_2 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_3 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_4 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_5 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_6 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_7 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
FS15_8 as string*12 ' 05 FS15 PIC S9(9)V99 computational-3
...
FS17_8 as string*12 ' 03 FS17 PIC S9(9)V99 computational-3
FS17_9 as string*12 ' 03 FS17 PIC S9(9)V99 computational-3
FS17_10 as string*12 ' 03 FS17 PIC S9(9)V99 computational-3
FS18 as string*6 ' 03 FS18 PIC 9(6)
FS19 as string*1 ' 03 FS19 PIC 9
FC8LF As String * 2 ' LF 11
End Type
创建 table 过程
每个字段都变成了一个对象(来自我创建的自定义 class),SQLtypeFull
在每个字段的 returns MySQL 数据类型下面使用了方法 SQLtypeFull
=21=]
'========================================================================
Private Function Create_Table_MySQL() As Boolean
On Error GoTo Erreur
Dim Rs As Recordset
Dim SQL As String
SQL = "CREATE TABLE IF NOT EXISTS `TBL_DAT_FACTURE` ( `ID` INT(11) NOT NULL auto_increment, `RECID` INT(11)"
SQL = SQL & ", `FS1` " & FS1.SQLtypeFull
SQL = SQL & ", `FS2` " & FS2.SQLtypeFull
SQL = SQL & ", `FS2A` " & FS2A.SQLtypeFull
SQL = SQL & ", `RFS2B` " & RFS2B.SQLtypeFull
SQL = SQL & ", `FS2B` " & FS2B.SQLtypeFull
SQL = SQL & ", `FS3` " & FS3.SQLtypeFull
SQL = SQL & ", `FS3A` " & FS3A.SQLtypeFull
SQL = SQL & ", `FS3B` " & FS3B.SQLtypeFull
SQL = SQL & ", `FS4` " & FS4.SQLtypeFull
SQL = SQL & ", `FS4A` " & FS4A.SQLtypeFull
SQL = SQL & ", `FS4B` " & FS4B.SQLtypeFull
SQL = SQL & ", `FS4C` " & FS4C.SQLtypeFull
SQL = SQL & ", `FS5` " & FS5.SQLtypeFull
SQL = SQL & ", `FS6` " & FS6.SQLtypeFull
SQL = SQL & ", `FS7` " & FS7.SQLtypeFull
SQL = SQL & ", `FS8` " & FS8.SQLtypeFull
SQL = SQL & ", `FS9` " & FS9.SQLtypeFull
SQL = SQL & ", `FS10` " & FS10.SQLtypeFull
SQL = SQL & ", `FS11` " & FS11.SQLtypeFull
SQL = SQL & ", `FS12` " & FS12.SQLtypeFull
SQL = SQL & ", `FS13` " & FS13.SQLtypeFull
SQL = SQL & ", `FS14_15_1` " & FS14_15_1.SQLtypeFull
SQL = SQL & ", `FS14_15_2` " & FS14_15_2.SQLtypeFull
SQL = SQL & ", `FS14_15_3` " & FS14_15_3.SQLtypeFull
SQL = SQL & ", `FS14_15_4` " & FS14_15_4.SQLtypeFull
SQL = SQL & ", `FS14_15_5` " & FS14_15_5.SQLtypeFull
SQL = SQL & ", `FS14_15_6` " & FS14_15_6.SQLtypeFull
SQL = SQL & ", `FS14_15_7` " & FS14_15_7.SQLtypeFull
SQL = SQL & ", `FS14_15_8` " & FS14_15_8.SQLtypeFull
SQL = SQL & ", `FS14_15_9` " & FS14_15_9.SQLtypeFull
SQL = SQL & ", `FS14_15_10` " & FS14_15_10.SQLtypeFull
SQL = SQL & ", `FS14_1` " & FS14_1.SQLtypeFull
SQL = SQL & ", `FS14_2` " & FS14_2.SQLtypeFull
SQL = SQL & ", `FS14_3` " & FS14_3.SQLtypeFull
SQL = SQL & ", `FS14_4` " & FS14_4.SQLtypeFull
SQL = SQL & ", `FS14_5` " & FS14_5.SQLtypeFull
SQL = SQL & ", `FS14_6` " & FS14_6.SQLtypeFull
SQL = SQL & ", `FS14_7` " & FS14_7.SQLtypeFull
SQL = SQL & ", `FS14_8` " & FS14_8.SQLtypeFull
SQL = SQL & ", `FS14_9` " & FS14_9.SQLtypeFull
SQL = SQL & ", `FS14_10` " & FS14_10.SQLtypeFull
SQL = SQL & ", `FS15_1` " & FS15_1.SQLtypeFull
SQL = SQL & ", `FS15_2` " & FS15_2.SQLtypeFull
SQL = SQL & ", `FS15_3` " & FS15_3.SQLtypeFull
SQL = SQL & ", `FS15_4` " & FS15_4.SQLtypeFull
SQL = SQL & ", `FS15_5` " & FS15_5.SQLtypeFull
...
SQL = SQL & ", `FS17_9` " & FS17_9.SQLtypeFull
SQL = SQL & ", `FS17_10` " & FS17_10.SQLtypeFull
SQL = SQL & ", `FS18` " & FS18.SQLtypeFull
SQL = SQL & ", `FS19` " & FS19.SQLtypeFull
SQL = SQL & ", PRIMARY KEY (`ID`)"
SQL = SQL & ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE utf8_bin;"
MySQLcon.Execute (SQL)
Create_Table_MySQL = True
Exit_Sub:
Exit Function
Erreur:
Create_Table_MySQL = False
Resume Exit_Sub
End Function
最终SQL声明
CREATE TABLE IF NOT EXISTS `FACTURE`
( `ID` INT(11) NOT NULL auto_increment, `RECID` INT(11), `FS1` CHAR(1), `FS2` CHAR(9), `FS2A` TINYINT(1) UNSIGNED, `RFS2B` CHAR(8), `FS2B` INT(8) UNSIGNED, `FS3` CHAR(11), `FS3A` TINYINT(1) UNSIGNED, `FS3B` CHAR(10), `FS4` CHAR(6), `FS4A` TINYINT(2) UNSIGNED, `FS4B` TINYINT(2) UNSIGNED, `FS4C` TINYINT(2) UNSIGNED, `FS5` CHAR(5), `FS6` CHAR(20), `FS7` TINYINT(1) UNSIGNED, `FS8` DECIMAL(11,2), `FS9` DECIMAL(11,2), `FS10` TINYINT(1) UNSIGNED, `FS11` DECIMAL(11,2), `FS12` DECIMAL(11,2), `FS13` DECIMAL(11,2), `FS14_15_1` CHAR(13), `FS14_15_2` CHAR(13), `FS14_15_3` CHAR(13), `FS14_15_4` CHAR(13), `FS14_15_5` CHAR(13), `FS14_15_6` CHAR(13), `FS14_15_7` CHAR(13), `FS14_15_8` CHAR(13), `FS14_15_9` CHAR(13), `FS14_15_10` CHAR(13), `FS14_1` TINYINT(1) UNSIGNED, `FS14_2` TINYINT(1) UNSIGNED, `FS14_3` TINYINT(1) UNSIGNED, `FS14_4` TINYINT(1) UNSIGNED, `FS14_5` TINYINT(1) UNSIGNED, `FS14_6` TINYINT(1) UNSIGNED, `FS14_7` TINYINT(1) UNSIGNED, `FS14_8` TINYINT(1) UNSIGNED, `FS14_9` TINYIN
T(1) UNSIGNED, `FS14_10` TINYINT(1) UNSIGNED, `FS15_1` DECIMAL(11,2), `FS15_2` DECIMAL(11,2), `FS15_3` DECIMAL(11,2), `FS15_4` DECIMAL(11,2), `FS15_5` DECIMAL(11,2), `FS15_6` DECIMAL(11,2), `FS15_7` DECIMAL(11,2), `FS15_8`
...
DECIMAL(11,2), `FS17_10` DECIMAL(11,2), `FS18` DATE, `FS19` TINYINT(1) UNSIGNED,
PRIMARY KEY (`ID`)) ENGINE=MyISAM
DEFAULT CHARSET=utf8 COLLATE utf8_bin;
我在生成的 VBA 模块中有更多内容,生成的 xml 的详细程度和准确性对所有模块都有很大帮助:
- 我创建了一个 Class 来管理字段的所有方面,特别是处理原始 PICTURE 和 VBA 类型(日期、长、双精度)后的转换 VBA/MySQL , currency, etc...) 还有一个挂钩,以防你想强制使用另一种类型。
- 它完全处理元数据创建(也在 MySQL 中)
- 它处理导入数据时的错误,在文件和字段级别记录所有内容
我可能已经展示了足够多的东西给你一些想法,所以我就到此为止了。
最重要的:当我们运行将在 COBOL ERP 中进行的复杂计算放入 SQL 语句时 运行在新的数据仓库中,数据库返回的数字与 ERP 中的数字完全相同。在数百万条记录上,计算中没有一位数字的损失。这是证明它有效的最好方法:-)
如果您想知道为什么我使用 Access/VBA 而不是 .NET 进行导入:这是一个没有商量余地的要求。
最后一点:我与 CB2XML 没有任何关联,这不是它的广告。这是一款非常有用的软件,值得关注。