|
August 2005 Technical Tip - Variable Length Records: VB, RDW, BDW, Oh
my!
One-to-many relationships are common in business systems. For example,
one sales rep can have many customers, one customer can have many
invoices, one invoice can have many items, etc. In modern systems, these
relationships would likely be implemented with a relational database
system using joins of multiple tables. In legacy systems, such
relationships were commonly implemented in a hierarchical database or,
more simply, with variable length records. This article will focus on how
variable length records are stored internally.
To illustrate, consider the following credit card example. Let's assume
one person can have many credit cards, but each credit card belongs to one
and only one person. Since each record will have a variable number of
credit cards, the record will typically include a field which indicates
how many. We will choose an arbitrary maximum of 3 credit cards per person
(artifically low to simplify our example.) The fixed portion of each
record will contain an ID number (3 bytes), first name (10 bytes), last
name (10 bytes), and occurances count (2 bytes), for a total of 25 bytes.
For each credit card we will store the credit card number (4 bytes),
credit card type (4 bytes) and balance due (4 bytes), for a total of 12
bytes. So each record contains from 25 bytes to 61 bytes (25 +
(3*12)).
When the system stores a variable length record, it puts a four byte
record descriptor word (RDW) on the front of each record. This RDW is not
always visible (such as within a COBOL program) but it's there. The first
two bytes of the RDW is a binary halfword (PIC S9(4) COMP) containing the
length of the record. This length includes the data and the RDW itself.
Consequently, our RDW will have a value of 29 to 65. This highest number
(65) will be the LRECL when we allocate the file. The second two bytes of
the RDW contains X'0000'.
We can allocate a simple variable length file with ISPF panel 3.2. For
example:
Menu RefList Utilities Help
______________________________________________________________________________
Allocate New Data Set
Command ===>
Data Set Name . . . : U0290.CREDIT.CARDS
Management class . . . MCTSOX (Blank for default management class)
Storage class . . . . SCBASE (Blank for default storage class)
Volume serial . . . . XTSO05 (Blank for system default volume) **
Device type . . . . . (Generic unit or device address) **
Data class . . . . . . (Blank for default data class)
Space units . . . . . TRACK (BLKS, TRKS, CYLS, KB, MB, BYTES
or RECORDS)
Average record unit (M, K, or U)
Primary quantity . . 1 (In above units)
Secondary quantity 1 (In above units)
Directory blocks . . 0 (Zero for sequential data set) *
Record format . . . . VB
Record length . . . . 65
Block size . . . . . 0
Data set name type : (LIBRARY, HFS, PDS, or blank) *
(YY/MM/DD, YYYY/MM/DD
Expiration date . . . YY.DDD, YYYY.DDD in Julian form
|
We can then edit the file with ISPF panel 2. Be sure to choose the
Preserve VB record length option!
Menu RefList RefMode Utilities Workstation Help
______________________________________________________________________________
Edit Entry Panel
Command ===>
ISPF Library:
Project . . . U0290
Group . . . . ISPF . . . . . . . . .
Type . . . . CNTL
Member . . . (Blank or pattern for member selection list)
Other Partitioned, Sequential or VSAM Data Set:
Data Set Name . . . credit.cards
Volume Serial . . . (If not cataloged)
Workstation File:
File Name . . . . .
Options
Initial Macro . . . . Confirm Cancel/Move/Replace
Profile Name . . . . . Mixed Mode
Format Name . . . . . Edit on Workstation
Data Set Password . . / Preserve VB record length
|
We can enter the data as follows. Note that although the LRECL is 65,
the ruler (from the COLS command) only goes out to column 61. The
difference is the RDW (4 bytes) which is not seen.
File Edit Edit_Settings Menu Utilities Compilers Test Help
_______________________________________________________________________________
EDIT U0290.CREDIT.CARDS Columns 00001 00061
Command ===> Scroll ===> HALF
****** ***************************** Top of Data ******************************
=COLS> ----+----1----+----2----+----3----+----4----+----5----+----6-
000001 987BILL QUALLS 035555VISA10002345MAST05001234DISC0100
000002 123RUBECCA ALINIAZEE 011010VISA0000
000003 786ERIC ALBERT 022323MAST01003434DISC9999
000004 432JASON ROGERS 017777DISC0750
****** **************************** Bottom of Data ****************************
|
IDCAMS can be used to dump the file. The JCL appears as follow:
File Edit Edit_Settings Menu Utilities Compilers Test Help
_______________________________________________________________________________
EDIT U0290.ISPF.CNTL(DUMPVB) - 01.00 Columns 00001 00072
Command ===> Scroll ===> HALF
****** ***************************** Top of Data ******************************
000001 //U0290DMP JOB (PRM,0,T),'BILL QUALLS',
000002 // CLASS=A,MSGCLASS=T,TIME=(0,59),NOTIFY=U0290
000003 //STEP010 EXEC PGM=IDCAMS
000004 //MYINPUT DD DSN=U0290.CREDIT.CARDS,DISP=SHR
000005 //SYSIN DD *
000006 PRINT INFILE(MYINPUT) DUMP
000007 //SYSPRINT DD SYSOUT=*
****** **************************** Bottom of Data ****************************
|
We can see from the following dump that the records are, in fact,
varying in length.
LISTING OF DATA SET -U0290.CREDIT.CARDS
RECORD SEQUENCE NUMBER - 1
000000 F9F8F7C2 C9D3D340 40404040 40D8E4C1 D3D3E240 404040F0 F3F5F5F5 F5E5C9E2 *987BILL QUALLS 035555VIS*
000020 C1F1F0F0 F0F2F3F4 F5D4C1E2 E3F0F5F0 F0F1F2F3 F4C4C9E2 C3F0F1F0 F0 *A10002345MAST05001234DISC0100 *
RECORD SEQUENCE NUMBER - 2
000000 F1F2F3D9 E4C2C5C3 C3C14040 40C1D3C9 D5C9C1E9 C5C540F0 F1F1F0F1 F0E5C9E2 *123RUBECCA ALINIAZEE 011010VIS*
000020 C1F0F0F0 F0 *A0000 *
RECORD SEQUENCE NUMBER - 3
000000 F7F8F6C5 D9C9C340 40404040 40C1D3C2 C5D9E340 404040F0 F2F2F3F2 F3D4C1E2 *786ERIC ALBERT 022323MAS*
000020 E3F0F1F0 F0F3F4F3 F4C4C9E2 C3F9F9F9 F9 *T01003434DISC9999 *
RECORD SEQUENCE NUMBER - 4
000000 F4F3F2D1 C1E2D6D5 40404040 40D9D6C7 C5D9E240 404040F0 F1F7F7F7 F7C4C9E2 *432JASON ROGERS 017777DIS*
000020 C3F0F7F5 F0 *C0750 *
|
But what about the RDW? The RDW is usually not shown, but there is a
trick you can use to force its display. This involves adding DCB=RECFM=U
to the JCL as follows:
File Edit Edit_Settings Menu Utilities Compilers Test Help
_______________________________________________________________________________
EDIT U0290.ISPF.CNTL(DUMPVB) - 01.00 Columns 00001 00072
Command ===> Scroll ===> HALF
****** ***************************** Top of Data ******************************
000001 //U0290DMP JOB (PRM,0,T),'BILL QUALLS',
000002 // CLASS=A,MSGCLASS=T,TIME=(0,59),NOTIFY=U0290
000003 //STEP010 EXEC PGM=IDCAMS
000004 //MYINPUT DD DSN=U0290.CREDIT.CARDS,DISP=SHR,DCB=RECFM=U
000005 //SYSIN DD *
000006 PRINT INFILE(MYINPUT) DUMP
000007 //SYSPRINT DD SYSOUT=*
****** **************************** Bottom of Data ****************************
|
The resulting dump is at the same time confusing and revealing:
LISTING OF DATA SET -U0290.CREDIT.CARDS
RECORD SEQUENCE NUMBER - 1
000000 00CC0000 00410000 F9F8F7C2 C9D3D340 40404040 40D8E4C1 D3D3E240 404040F0 *........987BILL QUALLS 0*
000020 F3F5F5F5 F5E5C9E2 C1F1F0F0 F0F2F3F4 F5D4C1E2 E3F0F5F0 F0F1F2F3 F4C4C9E2 *35555VISA10002345MAST05001234DIS*
000040 C3F0F1F0 F0002900 00F1F2F3 D9E4C2C5 C3C3C140 4040C1D3 C9D5C9C1 E9C5C540 *C0100....123RUBECCA ALINIAZEE *
000060 F0F1F1F0 F1F0E5C9 E2C1F0F0 F0F00035 0000F7F8 F6C5D9C9 C3404040 404040C1 *011010VISA0000....786ERIC A*
000080 D3C2C5D9 E3404040 40F0F2F2 F3F2F3D4 C1E2E3F0 F1F0F0F3 F4F3F4C4 C9E2C3F9 *LBERT 022323MAST01003434DISC9*
0000A0 F9F9F900 290000F4 F3F2D1C1 E2D6D540 40404040 D9D6C7C5 D9E24040 4040F0F1 *999....432JASON ROGERS 01*
0000C0 F7F7F7F7 C4C9E2C3 F0F7F5F0 *7777DISC0750 *
|
Look at the first line and you will see 00410000. This is the
RDW for the first record. X'0041' is the hexadecimal representation of the
number 65 (4 * 16 + 1). This is the total length of the first record. Find
00290000 in the third line. This is the RDW for the second record:
29 base 16 = 41 base 10. Similarly, you will see 00350000 in the
fourth line and 00290000 in the sixth line, representing the
lengths of the third (53) and fourth (41) records respectively.
Just as an RDW describes each record, a BDW describes each block. Find
00CC0000 in the first line. CC base 16 = 204 base 10. This is the
length of the block: 65 (first) + 41 (second) + 53 (third) + 41 (fourth) +
4 (for the BDW itself.)
I hope this article helped you to understand variable length records.
In next month's
article I will show you how to reformat variable length records using
SyncSort. Until then, we hope you will continue to consider Caliber Data
Training when searching for an IT training provider.
Go to the articles index. Written
by Bill Qualls. Copyright © 2005 by Caliber Data Training
800.938.1222 |