Contents
Variable
Length Records – Variable Occurrences.
Variable
Length Records – Different Record Types
Write is used to create a new record on a file or database. It corresponds to SQL’s INSERT and COBOL’s WRITE statement, and is usually used when creating a new file. It is rarely used in other circumstances: -
·
With VSAM, it can only be used with empty (new)
VSAM files, and it is NOT used to insert records into existing VSAM files. Instead use
GET VSAMF WHERE (….) UPDATE;
… Statements to set VSAMF field
values
END GET VSAMF UPDATE;
This GET/END GET logic will deal with record-not-found by creating a new records and using a COBOL WRITE, and with record-found by using REWRITE. Refer to https://www.jazzsoftware.co.nz/Docs/JazzLRM_GET.htm for more information.
· You will usually use PROCESS … COPY, including PROCESS … MERGE … COPY, to create an updated copy of the primary file. Refer to https://www.jazzsoftware.co.nz/Docs/JazzUGmerge.htm#MergeCopy for more information.
WRITE FileName [[DATA] (RecordName) |
FROM (RecordName2)]
Use this option when Filename is defined without a DATA option. See the second example below. Do not name the file’s own record layout in this way, e.g. this is invalid: -
WRITE FILEV2 (FILEV2.*);
If FROM is present,
then data from RecordName2 is written out.
RecordName2 can be the record layout of the file, for example
WRITE FILEV2 FROM(FILEV2.*);
This is
equivalent to this WRITE which uses neither DATA nor FROM option: -
WRITE FILEV2;
With FROM you can name a record from another file, or working data, ignoring any DATA option defined with the file’s definition.
PROGRAM
CopyIN1 BATCH;
COPY
IN1;
COPY
out1;
PROCESS
in1;
Out1.* = In1.*;
#207 I Region, District,
Name, BillingCycle included in generic assignment
WRITE
out1;
#378 W Batch
WRITE used - you may need to edit the JCL
END PROCESS in1;
DATA is a
default keyword, so you can write WRITE Outfile (Infile.*); instead of WRITE Outfile DATA (Infile.*); If a DATA option
is used (or implied), then the DEFINE
statement for the output file does not need a DATA option. For example, to write a subset of the
records from Infile without reformatting them: -
PROGRAM Copy2;
DEFINE InFile VB DATA(
Field1
…,
Field2 ,,,
Field3 …);
DEFINE OutFile TYPE(...)
PROCESS Infile WHERE condition;
WRITE Outfile (Infile.*);
END PROCESS Infile;
FileName names a file that has been defined in a preceding DEFINE statement. The file must have type VSAM, F, FB, V, VB, U, XIO, SQL, or TS. Other types (WorkingData, SCREEN, Parameter, etc) are not permitted.
RecordName defines a redefinition of the file. Thus with
DEFINE FILEO VB DATA(…
DEFINE FILEO-HDR-RECORD REDEFINES
DATA(…
DEFINE FILEO-X-USA-RECORD REDEFINES
DATA(
Valid WRITE statements for FileO are
WRITE FILEO;
WRITE FILEO(FILEO-HDR-RECORD.*);
WRITE FILEO(FILEO-X-USA-RECORD.*);
References to another definition would cause an error message.
If DATA is omitted from the WRITE statement: -
· VSAM and Physical-sequential Files: A record consisting of the record defined in the file’s DATA option is written. If there are redefinitions within this, then the longest possible record is written.
· SQL: all the fields defined in the table definition will be written. Nullable fields are written with their null indicator, so they may be written as NULL. NULL is almost always the default for SQL nullable fields.
In older systems you may come across VSAM or Physical-Sequential files with records that may vary in length with 0 to ?? occurrences of a group (or field). For example, here is a record describing the sales history of a product for the last 12 months: -
DEFINE PRODHIST VB DATA(
ProdCode PIC '999999',
SalesRegion PIC '999',
NbrMths SMALLINT,
MonthlySales(12(PRODHIST.NbrMths)) GROUP,
Month CODES(January,February,March,April,May,June,July,August,September,October,November,December),
NbrUnitsSold DECIMAL(5),
ValueSold MONEY(11,2),
End GROUP);
With MonthlySales(12(PRODHIST.NbrMths) there are from 0 to 12 occurrences of the group, each containing the month code and a value for NbrUnitsSold and ValueSold that month. When the record is written only the number of occurrences in PRODHIST.NbrMths is written.
Records like this are rarely, if ever, used in modern design, as they are difficult to manage without risking errors. If you have read a record with 6 occurrences (for example), then you MUST NOT refer to MonthlySales(7). You must NEVER increase the number of occurrences beyond the maximum. Assignments such as
PRODHIST.NbrMths = 13;
PRODHIST.NbrUnitsSold(PRODHIST.NbrMths) = 123;
will cause unpredictable results, with potentially catastrophic program failure.
A common sequential file design allows several different record types within a single file. For example the first record might be a Header record, followed by several Detail records, with a final Trailer. Perhaps there are Customer, Customer-Purchase, and Customer-Payment records. Every record starts with a common section of at least 1 byte that allows a program to read the record and know what type it is dealing with. For example, in FileIN there are several different record types with a common 8 byte section: -
DEFINE FILEIN VB DATA(
COMMON GROUP,
ORG-X GROUP,
ORG PIC '999',
END GROUP,
AFF CHAR(4) CONDITIONS('X1 ','X2 ','X3 ','X4 ','X5 ','X6 ','X7 ','X8 ','X9 ','XA ','XB ','XC ','XD ','XE ','XF ','XG ','XH ','XI ','XJ ','XP ','XS ':VALID-XX-AFF),
AFF-FLAG GROUP REDEFINES FILEIN.AFF,
AFF-2 CHAR(3),
AFF-BYTE4 CHAR(1),
END GROUP,
REC-STAT PIC '9',
END GROUP,
FILLER CHAR(10284))
DSNAME 'MANAJAZZ.FILES.FILEIN';
DEFINE FILE-HDR-RECORD REDEFINES
DATA(
FILLER CHAR(8),
HDR-PROC-DATE DECIMAL(7),
HDR-TIME-STAMP DECIMAL(11));
DEFINE FILE-X-USA-RECORD REDEFINES
DATA(
FILLER CHAR(8),
VI-X-QP-REGION CHAR(1),
VI-MC-QP-REGION CHAR(1),
VI-EU-QP-REGION CHAR(1),
X-RPT-SCHEDULES GROUP,
X-SCHEDULES-A-B(13) GROUP,
X-SCHEDULE-A GROUP,
…
The first definition defines the file type (VB), a record that contains the common area, and enough space for the largest record. It also contains the DSNAME. Then follows a number of redefinitions of the initial record. FILEO has the same structure: -
DEFINE FILEO VB DATA(
…
DEFINE FILEO-HDR-RECORD REDEFINES
DATA(
…
DEFINE FILEO-X-USA-RECORD REDEFINES
DATA(
…
A program to copy data from FILEIN to FILEO has the usual PROCESS loop to read the input. Within this loop an initial common section handles the common fields, then CASE or IF … ELSEIF … logic is used to copy and write out the particular record type, using WRITE filename(record) to write the particular record type involved: -
PROCESS FILEIN;
*
$Common
FILEO.ORG=FILEIN.ORG;
FILEO.AFF=FILEIN.AFF;
FILEO.REC-STAT=FILEIN.REC-STAT;
IF FILEIN.ORG=0; [Header
FILEO-HDR-RECORD.HDR-PROC-DATE=FILE-HDR-RECORD.HDR-PROC-DATE;
FILEO-HDR-RECORD.HDR-TIME-STAMP=FILE-HDR-RECORD.HDR-TIME-STAMP;
WRITE FILEO(FILEO-HDR-RECORD.*);
ELSEIF FILEIN.AFF=VALID-XX-AFF;
[X-USA-RECORD
FILEO-X-USA-RECORD.VI-X-QP-REGION=FILE-X-USA-RECORD.VI-X-QP-REGION;
FILEO-X-USA-RECORD.VI-MC-QP-REGION=FILE-X-USA-RECORD.VI-MC-QP-REGION;
FILEO-X-USA-RECORD.VI-EU-QP-REGION=FILE-X-USA-RECORD.VI-EU-QP-REGION;
WRITE FILEO(FILEO-X-USA-RECORD.*);
END IF;
END PROCESS FILEIN;