Динамическое чтение COBOL переопределяет с помощью C#
Я делаю программу на C#, которая сможет динамически читать IBM HOST Copybook, написанную на языке COBOL, и генерировать из нее таблицу SQL. После того, как таблица сгенерирована, я могу загрузить файл в мою программу, и он будет читать, конвертировать из IMB-37 и вставлять файл в эту таблицу SQL. Пока что я могу справиться почти с чем угодно, хотя у меня возникают некоторые проблемы с 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).
Я попытался просто игнорировать переопределения, так как оно всегда будет занимать одинаковое количество места, но в случае, когда оригинальное поле упаковано, а переопределенное не мне, мне нужно знать, когда распаковывать поле.
Любая помощь с этим была бы удивительными парнями!
2 ответа
Я могу, возможно, помочь вам, так как 2 года назад я достиг именно того, что вы делаете сейчас.
Мне пришлось спроектировать MySQL Datawarehouse, включая систему ETL, основанную исключительно на файлах из приложения RM COBOL ERP, работающего в Linux. В приложении было более 600 файлов, и до сих пор неясно, сколько из них наконец попадет в базу данных. Большинство важных файлов были проиндексированы в полях COMP, чтобы сделать его сложнее, и одно из очевидных требований состояло в том, чтобы все отношения между файлами и их индексированными ключами можно было воспроизвести в базе данных. Поэтому мне потенциально требовалось каждое поле каждого файла.
Учитывая количество файлов, не было никакой необходимости обрабатывать все файлы вручную и один за другим.
Таким образом, моя идея заключалась в том, чтобы написать код для приложения VB.NET, которое принимает на вход тетради COBOL и
- Генерирует программы на языке COBOL, которые преобразуют данные во что-то пригодное для использования, читая оригинальные проиндексированные файлы и записывая записи в последовательный текстовый файл.
- Создает модули VBA со всем кодом, необходимым для импорта этих файлов данных из MS Access в MySQL (включая CREATE TABLE и Indexes)
В начале проекта я столкнулся с теми же проблемами, что и вы сейчас, особенно с этими чертовыми ПЕРЕПИСКАМИ. Я нашел задачу перечисления и кодирования всех возможностей тетради, если не невозможно, хотя бы опасно. Итак, я посмотрел в другую сторону, и нашел это:
CB2XML
COBOL тетрадь в XML конвертер: SourceForge
Это сэкономило мне несколько недель тяжелой работы по разбору и интерпретации тетради. Он может анализировать тетради COBOL, чтобы преобразовать их в XML-файл, в котором идеально описывается вся картинка с множеством полезных атрибутов, таких как длина или тип. Он полностью поддерживает стандарты COBOL'86.
Пример:
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
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, которые преобразуют проиндексированные файлы (читаемые только с помощью среды выполнения cobol RM) в плоские файлы, работают со всеми полями, включая ARRAYS и REDEFINES.
- Для REDEFINES: я создаю поле как для "основной" PICTURE, так и для этого REDEFINES, и их тип соответствует их COBOL PICTURE
- Для ARRAY я создаю поле для каждого элемента, а также огромное поле, содержащее весь массив "line"
- Для ВЫЧИСЛИТЕЛЬНЫХ полей я просто перемещаю оригинальный COMP в точно такое же изображение на дисплее
Не все поля имеют цель, когда они находятся в базе данных, но по крайней мере все доступно постоянно
С файлом выше, ПОСЛЕДОВАТЕЛЬНАЯ тетрадь текстового файла становится такой:
Автоматически сгенерированный 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.
ДВИЖЕНИЕ инструкции
* ============================================================
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
После записи плоских файлов они могут быть обработаны в MySQL с помощью кода VBA, также сгенерированного приложением 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
Процедура создания таблицы
Каждое поле стало объектом (из созданного мной пользовательского класса), а метод SQLtypeFull
используется ниже, возвращает тип данных MySQL каждого поля
'========================================================================
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 очень помог им всем:
- Я создал класс, который управляет всеми аспектами полей и, в частности, позаботится о преобразованиях VBA/MySQL, следуя оригинальным типам PICTURE и VBA (date, long, doubles, currency и т. Д.), И есть ловушка на случай, если вы хочу заставить другой тип.
- он полностью связан с созданием метаданных (также в MySQL)
- он работает с ошибками при импорте данных, регистрируя все на уровне файлов и полей
Я, наверное, показал достаточно, чтобы дать вам несколько идей, поэтому я на этом остановлюсь.
Самое важное: на нескольких сотнях тысяч записей я не потерял ни одной цифры при вычислениях. Когда я SUM() для всех строк, используя SQL в базе данных, у меня есть точно такие же числа, что и исходное приложение COBOL
Если вам интересно, почему я использовал Access/VBA, а не.NET для импорта: это было не подлежащим обсуждению требованием -_-
И последнее замечание: я никак не связан с CB2XML, и это не реклама для него. Это просто отличная и полезная часть программного обеспечения, которая заслуживает любви и внимания.
REDEFINES
собирается сделать вашу задачу более сложной. Интуитивно понятно, что "компилятор" не знает, какое именно поле использовать, а то, что код в существующей системе 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 для использования одних и тех же мест хранения в записи для взаимоисключающих ситуаций. Экономит хранилище, которое было дорого. Система, с которой вы работаете, либо "старая", либо ее конструкция заражена ложным "опытом".
У вас есть два широких варианта: реплицировать весь условный выбор данных (чтобы у вас было два набора бизнес-логики, чтобы идти в ногу); чтобы изменить файл так, чтобы каждое поле занимало свое собственное хранилище.
Наличие типов данных COMP-3 (или PACKED-DECIMAL) или COMP/COMP-4/COMP-5/BINARY также усложняет вам задачу. Затем вам потребуется выполнить EBCDIC-to-ASCII на уровне поля для реальных данных EBCDIC и сделать все, что необходимо для преобразования или простого получения "вычислительных" данных.
Также имейте в виду, что любые числовые поля со знаком DISPLAY-числовые (числовые поля с PICture, начинающимся с S, но без явного "вычислительного" использования), по-видимому, будут содержать "символьные" данные в последнем байте, поскольку знак хранится как " overpunch "последнего байта.
Обратите внимание, что двоичные типы данных будут Big Endian.
Для вас будет намного проще, если вы получите файлы, в которых нет REDEFINES, нет "вычислительных" полей и нет встроенных знаков (или неявных десятичных разрядов). Все ваши данные будут символьными, и вы можете EBCDIC-to-ASCII на уровне записи (или на уровне файлов, с вашим механизмом передачи файлов).
Если вы посмотрите на вопросы, помеченные здесь как COMP-3, вы найдете дальнейшее обсуждение этого, и если вы решите, что единственно возможный путь - нелепый маршрут (ваша программа понимает нативные элементы данных COBOL мэйнфрейма, а не простой текст). чтобы пойти, то есть ряд вещей в обсуждениях, которые вы можете найти полезными и сможете использовать или применять.
Если ваша компания "регулируется" извне, убедитесь, что ваши отделы соответствия, аудита и бухгалтерии довольны вашим дизайном, прежде чем писать одну строку. Упс. Опоздал на это. Будем надеяться, что это производство.