Проблема с обработкой файлов RPG IV

Я все еще изучаю RPG и AS/400. исходя из MS C#.NET. в настоящее время мы переходим на машину iSeries, и я пытаюсь освоить программирование IBM RPG и CL, так как это больше необходимо для компании.

версия iSeries, если я правильно понимаю, это dspdtaara QSS1MRI: ==> "V7R1M000 2924"

DSPSFWRSC+ F11 : ==>

 5770999   *BASE    5050     *CODE   QSYS        V7R1M0 L00 
 5770SS1   *BASE    5050     *CODE   QSYS        V7R1M0 L00 
 5770SS1   *BASE    2924     *LNG    QSYS        V7R1M0 L00    
 ... 
 5770WDS   56       5101     *CODE   QDEVTOOLS   V7R1M0  
 5770WDS   60       5050     *CODE   QDEVTOOLS   V7R1M0  

вот моя проблема.

У меня есть плоский файл, созданный на старой машине AS400 и скопированный в новый файл iSeries, который представляет собой данные с разделителями (используя ";" ), которые мне нужно переформатировать и экспортировать на FTP для дальнейшей обработки сторонней компанией. каждая запись имеет 29 или 28 столбцов. таким образом, первое, что я делаю, это использую программу SQLRPGLE, добавляющую дополнительный разделитель к записям, в которых он отсутствует. в самом плоском файле

 C/EXEC SQL 
 C+ SELECT  
 C+   MAX((length(trim(F00001))- length(REPLACE(trim(F00001),';',''))))
 C+ , MIN((length(trim(F00001))- length(REPLACE(trim(F00001),';',''))))
 C+ INTO :MaxCount, :@DelimCount 
 C+ FROM QGPL.fIncomming  
 C/END-EXEC        

  **/*  using the delimiter could fix data by inserting a delimiter in the proper place */

 C/EXEC SQL  
 C+ UPDATE QGPL.fIncomming
 C+  SET F00001 = INSERT(F00001,225,0,';') 
 C+ WHERE ( :MaxCount
 C+         - (  length(trim(F00001))  
 C+            - length(REPLACE(trim(F00001),';','')) )
 C+       ) > 0 
 C/END-EXEC   

затем я создал 2 таблицы (PF) в iSeries

Table1, которая представляет собой таблицу SQL с 29 столбцами на основе формата входящего файла (все столбцы имеют имена и устанавливаются в соответствии с длиной данных, но все столбцы имеют текстовый (A) тип)

и вторая таблица (Таблица 2), которая имеет точно такой же макет, что и таблица (Таблица 1), но каждый столбец имеет определенный тип данных по мере необходимости. т. е. id — это INTEGER, а dateof — это DATE и т. д.

нет, данные не чистые. таким образом, в поле даты могут быть пробелы, а в поле денег может быть текст.

Мне нужен лучший способ переместить данные в таблицу2, очистив и проверив их во время передачи.
способ SQL был бы лучшим, но оператор настолько большой, что я не могу его правильно проверить.

может ли кто-нибудь предложить (с примером, если возможно) другие способы или лучший способ написать SQL для него
У меня в основном есть это, но я получаю много ошибок: и если я пытаюсь запустить его в STRSQL, не весь код подходит экран.

SELECT
 TRIM(ORDERID) as ORDERID
...,LINENUM) <> ''
      THEN TRIM(LINENUM) 
      ELSE 9999 END as LINENUM
, TRIM(CUSTNUM) as CUSTNUM
, TRIM(PONUM) as PONUM
, CASE WHEN TRIM(REPLACE(ORDDATE,0,'')) <> ''
       THEN CAST(INSERT(INSERT(ORDDATE,5,0,'/'),3,0,'/') as Date) 
...
from Table1

ПО ЗАПРОСУ: это исходные данные плоского файла [сначала им предшествуют заголовки столбцов c1-c29 для записей с 29 эффективными столбцами данных с разделителями, а затем — заголовки столбцов c1-c28 с *Err->, указывающим, где находится ожидаемый разделитель и 30 пробелов. отсутствует для вторичных записей, поскольку каждая запись должна иметь одинаковую разметку, а третья — встроенная линейка, показывающая 225-ю позицию, где точка с запятой будет добавлена ​​с предшествующей Код SQL и дополнительно 30 пробелов могут быть добавлены для сохранения макета фиксированной длины.]:

---c1----c2---c3----c4---------c5-------c6-------c7-------c8----------c9-----------c10-------c11--------------c12--------------c13----c14-c15---c16---c17---c18------c19---------c20------c21-----c22-------------c23-----------------------c24------------------c25----c26----c27------c28-----c29---
---c1----c2---c3----c4---------c5-------c6-------c7-------c8----------c9-----------c10-------c11--------------c12--------------c13----c14-c15---c16---c17---c18------c19---------c20------c21-----c22-------------c23-----*ERR->---c24--c25----c26-------c27-----c28-- **missing one column!**
....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+...10....+...11....+...12....+...13....+...14....+...15....+...16....+...17....+...18....+...19....+...20....+...21....+...22....+...23....+...24....+...25....+...26....+...27....+...28....+...29....+
1596555;001;10010;TEST5     ;01062015; 1213.00; 1219.00;  17.000;NET 30 DAYS ;            ;543534241;TOYYO1/5                ;  14OZ  ;T; 5.00; .500;   1; 560.00;          ;   560.00;01292015;5379602;** 2ND DAY **           ;5XDFSDFFGFGHGHGH16            ;      ;   ;          ;        ; 
1596555;   ;10010;          ;        ;        ;        ;        ;            ;            ;         ;                        ;        ; ;     ; .   ;    ;       ;          ;         ;01292015;5379602;                        ; 16.60;FRT;          ;        ; 
1598556;001;10021;TEST      ;02112015; 1237.00; 1207.00;  17.000;NET 30 DAYS ;            ;567860502;45GGH/4019              ;  10OZ  ;R;12.50; .000;   1; 105.42;          ;   105.42;02122015;5380313;** 2ND DAY **           ;3HGFH5456GFHFG5G27            ;      ;   ;          ;        ;
1598556;   ;10021;          ;        ;        ;        ;        ;            ;            ;         ;                        ;        ; ;     ; .   ;    ;       ;          ;         ;02122015;5380313;                        ; 13.19;FRT;          ;        ; 
1598557;001;10067;020415    ;02042015; 1283.00; 1238.00;  18.000;NET 30 DAYS ;            ;657870142;FTKG061/11              ;  14OZ  ;R;     ; .330;   1; 358.00;          ;   358.00;02092015;5380071;** 2ND DAY **           ;3NHJYJ64646GHJGHJ8            ;      ;   ;          ;        ;
1598557;   ;10067;          ;        ;        ;        ;        ;            ;            ;         ;                        ;        ; ;     ; .   ;    ;       ;          ;         ;02092015;5380071;                        ; 15.09;FRT;          ;        ;

И это желаемый результат, который в настоящее время генерируется процессом MS SQL [которому предшествует встроенная линейка]:

....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+...10....+...11....+...12....+...13....+...14....+...15....+...16....+...17....+...18....+...19....+...20....+...21....+
"1596555",1,"10010","TEST5",01/06/2015, 1213.00, 1219.00, 17.00,"NET 30 DAYS",,"543534241","TOYYO1/5","14OZ","T",5.00,0.50,1, 560.00,, 560.00,01/29/2015,"5379602","** 2ND DAY **","5XDFSDFFGFGHGHGH16",,,,,
"1596555",9999,"10010",,,,,,,,,,,,,,,,,,01/29/2015,"5379602",,,"16.60","FRT",,,
"1598556",1,"10021","TEST",02/11/2015, 1237.00, 1207.00, 17.00,"NET 30 DAYS",,"567860502","45GGH/4019","10OZ","R",12.50,0.00,1, 105.42,, 105.42,02/12/2015,"5380313","** 2ND DAY **","3HGFH5456GFHFG5G27",,,,,
"1598556",9999,"10021",,,,,,,,,,,,,,,,,,02/12/2015,"5380313",,,"13.19","FRT",,,
"1598557",1,"10067","020415",02/04/2015, 1283.00, 1238.00, 18.00,"NET 30 DAYS",,"657870142","FTKG061/11","14OZ","R",,0.33,1, 358.00,, 358.00,02/09/2015,"5380071","** 2ND DAY **","3NHJYJ64646GHJGHJ8",,,,,
"1598557",9999,"10067",,,,,,,,,,,,,,,,,,02/09/2015,"5380071",,,"15.09","FRT",,,

person vlad    schedule 09.04.2015    source источник
comment
Можете ли вы отредактировать свой вопрос, включив в него несколько репрезентативных строк файлов? Кроме того, укажите версию/выпуск ОС, чтобы мы знали, какие функции могут быть доступны.   -  person user2338816    schedule 10.04.2015
comment
конечно, user2338816, однако мое форматирование происходит повсюду, когда я публикую. хотя не знаю почему. может быть, потому что я подаю в суд на огненную лису?   -  person vlad    schedule 10.04.2015
comment
Они выглядят как записи переменной длины. Откуда вы знаете, что отсутствующий разделитель всегда находится в позиции 225?   -  person jmarkmurphy    schedule 10.04.2015
comment
извините, я забыл указать проблему более четко.   -  person vlad    schedule 10.04.2015
comment
всегда отсутствует разделитель на поз. 225 для записей с информацией о грузе. это в основном пустые строки с FRT в столбце 26. по какой-то причине эти записи объединяют столбцы для типа корабля и кода отслеживания ups при создании   -  person vlad    schedule 10.04.2015
comment
Рассматривали ли вы возможность использования ETL (см. Kettle, Talend в их бесплатной версии... или даже DataCleaner)? Отлично подходит для такого рода задач с IBM i (с драйвером jdbc jt400.jar), стоит вложений, если у вас больше такой работы. В чистом SQL вы быстро столкнетесь с неподдерживаемым кодом.   -  person Dam    schedule 10.04.2015
comment
Если форматы согласованы, я не вижу никаких проблем, используя только SQL, CPYFRMIMPF и CPYTOIMPF. Это, конечно, не было бы неприемлемым... при условии согласованных форматов. Немного трудно быть уверенным, потому что я не могу быть уверен, где записи начинаются и заканчиваются. Похоже, есть три примера FRT-записи, хотя они плохо отформатированы. (Я использую Firefox, и у меня нет проблем с публикацией строк или исходного кода здесь.)   -  person user2338816    schedule 11.04.2015
comment
ох, я вижу, данные искажены в сообщении. все концы записей были удалены. есть не 3 примера записей FRT, а 3 набора по 2 записи на учетную запись. первые столбцы всегда являются номером учетной записи и могут иметь несколько строк для каждой учетной записи, но последняя строка всегда является строкой записи FRT. Я выбрал учетные записи только с 2 строками на набор записей, чтобы упростить задачу. и, как я уже сказал, строка FRT всегда совпадает с основной строкой записи, за исключением отсутствующего разделителя в позиции 225, где он должен разделять столбцы типа корабля и номера отслеживания, все остальные столбцы присутствуют и учитываются.   -  person vlad    schedule 13.04.2015
comment
Ах! Это имеет больше смысла. Я отправил правку, чтобы посмотреть, поможет ли она нам всем понять. Мне кажется, что это можно сделать за несколько довольно простых шагов и, возможно, вообще без программирования, за исключением CL для выполнения шагов и, возможно, пары небольших сценариев SQL. Если будет создана пара рабочих таблиц, остальное будет довольно просто.   -  person user2338816    schedule 14.04.2015
comment
Хорошо, это не ответ, но мне удалось создать программу RPGLE, которая читает входящий файл, разбивает запись на столбцы по мере необходимости (поскольку все файлы в значительной степени имеют фиксированную длину, поскольку это было легко) и вставляет в целевую таблицу, помещая Нули в полях, когда входящие данные пусты. чем обычный процесс (CL, который я построил ранее) берет на себя и экспортирует таблицу в CSV по мере необходимости.   -  person vlad    schedule 14.04.2015


Ответы (2)


Я бы прочитал FIncomming прямо в программе RPG и не беспокоился об этом отсутствующем разделителе. Я предполагаю, что она в любом случае находится в конце записи (на самом деле вы нам этого не сказали). Разберите файлы, как в C/C++, стандартная библиотека C доступна для RPGIV. Для каждой записи проверьте поля и, если все они верны, напишите непосредственно в Таблицу 2, упомянутую в вашем вопросе. Записи с ошибками будут записаны в Таблицу 1 для исправления.

Теперь вы упомянули, что данные должны быть переданы по FTP внешней компании, это совсем другая проблема. У Скотта Клемента есть API, который вы можете использовать для FTP-файлов прямо из RPG. Его веб-сайт: http://www.scottklement.com.

И еще одно, учитывая, что вы новичок в RPG, вы можете изучить свободный формат, а не вариант с фиксированным форматом, поскольку это современный способ кодирования RPG. Этот оператор SQL в свободном формате будет выглядеть так:

  exec sql  
    UPDATE qgpl.fIncomming
      SET F00001 = INSERT(F00001,225,0,';')
      WHERE :MaxCount - length(trim(F00001) - length(REPLACE(trim(F00001),';',''))) > 0;

Существует много способов создать файл с разделителями-запятыми из файла базы данных. Самый простой - использовать команду CL CPYTOIMPF, запросить ее, и вы можете увидеть параметры. Эта команда также может поместить файл непосредственно в IFS с преобразованием в ASCII для передачи в MS-SQL.


Изменить 3 марта 2017 г.

Вау, похоже, некоторые люди используют действительно старые вещи. Итак, если вы используете версию i5/OS или OS/400 до V5R4, код выглядит следующим образом.

c/exec sql  
c+  UPDATE qgpl.fIncomming
c+    SET F00001 = INSERT(F00001,225,0,';')
c+    WHERE :MaxCount - length(trim(F00001) - length(REPLACE(trim(F00001),';',''))) > 0;
c/end-exec

Это фиксированный формат, обратите внимание на спецификацию c. Если вы программируете в свободном формате в этом старом выпуске и вам нужен прекомпилятор SQL, чтобы понять, что вы делаете, вам нужно будет добавить директивы компилятора /end-free и /free вокруг частей фиксированной формы вашего кода. @Dam включил ссылку в комментарии.

person jmarkmurphy    schedule 10.04.2015
comment
спасибо jmarkmurphy, FTP не проблема, у меня все работает. на самом деле он работал почти неделю, пока я не заметил, что данные не обрабатываются на FTP-сайте. это было, когда я сравнил исходный выходной файл из пакета MSSQL и тот, который я создавал на IBM, и увидел различия в форматировании. Я не знаю C/C++, поэтому не могу сказать, как там что-то разбирать. также бесплатный формат, как вы мне показываете, у меня не работает, не знаю почему. Я использую SQLRPGLE в качестве типа исходного файла для своей программы. - person vlad; 10.04.2015
comment
С V7R1 вы можете делать ролевую игру в свободной форме, следуя методу @jmarkmurphy, см. пример здесь: ссылка - person Dam; 10.04.2015
comment
Вы можете использовать метод свободной формы, который я показал, начиная с V5R4. Начиная с версии 7.1 вы можете определять спецификации H, F, D и P в свободном формате, а с помощью соответствующих групповых ptfs базы данных вы можете ссылаться на переменные хоста, определенные в свободном формате. - person jmarkmurphy; 11.04.2015
comment
Следующий комментарий: если вы получаете данные со старого AS400, почему это плоский файл? почему бы просто не сохранить его в файл сохранения, а затем передать его по ftp на новый iSeries? Убедитесь, что вы используете двоичный режим, но он должен работать нормально. Делали это много раз. Затем вы можете просто написать SQL для сопоставления старых полей с новыми полями, если это необходимо. - person jmarkmurphy; 11.04.2015
comment
проблема в том, что это, вероятно, уже файл сохранения. мы находимся в процессе перехода на новый iSeries со старого эмулятора AS/400+System36 (или 38). все рабочие материалы изначально находятся в Sys36/38 (не уверена в точной версии, поскольку она была обновлена ​​​​ранее), исходный файл был подготовлен и выведен из Sys36 изначально и до сих пор существует почти 2 года назад. по мере того как мы делаем преобразование, консультант, которого мы используем, ежедневно перемещает данные в iSeries и использует этот файл для вывода на локальный общий диск для использования с SQL. таким образом, я хочу использовать источник прямо сейчас. - person vlad; 13.04.2015
comment
Если вы можете манипулировать им с помощью SQL, это файл базы данных, а не файл сохранения. Файл сохранения должен быть восстановлен, прежде чем можно будет использовать содержащиеся в нем объекты. - person jmarkmurphy; 13.04.2015
comment
Я воспользовался вашим советом по обработке и просто использовал решения RPG, смешанные с приложениями SQL и CL. Я создал выходную таблицу на основе формата файла, прочитал каждую запись в RPG в DS, используя subst(), чтобы извлечь правильную информацию, а затем записать все в файл. чем с помощью приложения CL, я создаю CSV и загружаю его через FTP на сервер. благодаря. P.S. это немного больше работы, но на данный момент это менее хлопотно. - person vlad; 04.05.2015
comment
@Dam, ваша ссылка выше, добавленная 10 апр. - person mike; 02.03.2017
comment
@mike Не помню точно, какая техника программирования была в ссылке, но если речь идет о программировании в свободной форме с помощью SQL, здесь есть хорошее введение: Встраивание SQL в /free - person Dam; 03.03.2017
comment
@Dam, этот пример встраивает SQL фиксированной формы в программу произвольной формы. Если вы используете свободную форму, работает способ, который я показал выше. Если нет, то у вас либо старый релиз ‹ v5r4, либо вам нужен PTF. - person jmarkmurphy; 03.03.2017

Я не уполномочен [пока] «комментировать», поэтому вместо этого я использую функцию «ответ», чтобы запросить дополнительную информацию :-(
Что касается заявления в OP, что «я создал 2 таблицы (PF ) в iSeries", SQL DDL для этих двух объектов TABLE не был включен. Наличие этой информации позволило бы рецензентам сценария предложить некоторые идеи, используя уже определенные TABLE, а не рецензенту, предлагающему что-то еще. это может быть неприемлемо в рамках ограничений, установленных\установленных для сценария; мы можем только предположить, что эти две таблицы являются обязательными, учитывая, что операторы SELECT и UPDATE явно ссылаются на эти [еще не описанные] таблицы.?
FWiW, при представлении проблемы\сценария лучше всего предлагать все соответствующие детали [насколько это возможно] для получения полезной обратной связи; в противном случае тема заканчивается множеством комментариев с просьбами о дополнительных разъяснениях сценарий. nspired уже с этой темой.

person CRPence    schedule 18.04.2015
comment
Рад видеть тебя здесь, Чак. С вашим опытом/знаниями у вас не будет проблем с быстрым созданием достаточной репутации для комментариев. - person user2338816; 19.04.2015