WRITE

Contents

WRITE.. 1

Format 1

DATA.. 1

FROM.. 1

Examples. 1

Variable Length Records – Variable Occurrences. 2

Variable Length Records – Different Record Types. 2

 

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.

Format

WRITE FileName [[DATA] (RecordName) | FROM (RecordName2)]

DATA

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.*);

FROM

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.

Examples

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.

Variable Length Records – Variable Occurrences

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.

Variable Length Records – Different Record Types

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;