Programming on IBM i: sources, ILE, RPG and SQL Chapter 5 of 9

DDS and SQL: two ways of describing data

Reviewed on Verified on IBM i 7.5

Log in to save

On IBM i a file can be described in two ways, and the result is the same kind of object. A file created with DDS is queryable in SQL today with no conversion, and a table created with CREATE TABLE is readable by an RPG program like any other file.

These are not two databases: it is one database with two languages for describing it.

DDS

DDS (Data Description Specifications) is the column-based description, sibling to RPG's. A physical file:

     A          R ORDERSR
     A            ORDNUM         7P 0       TEXT('Order number')
     A            ORDCUS        10A         TEXT('Customer code')
     A            ORDDAT         7P 0       TEXT('Order date CYYMMDD')
     A            ORDAMT        11P 2       TEXT('Amount')
     A            ORDSTS         1A         TEXT('Status: O open')
     A          K ORDNUM

And a logical file, which is a view with a key of its own:

     A          R ORDERSR                   PFILE(ORDERS)
     A          K ORDCUS
     A          K ORDDAT

DDS also describes display files (DSPF) and printer files (PRTF), and for those there is no SQL equivalent: anyone working on 5250 screens will go on writing DDS anyway.

SQL

The same file, in DDL:

CREATE TABLE PRODLIB.ORDERS (
  ORDNUM  DECIMAL(7,0)   NOT NULL,
  ORDCUS  CHAR(10)       NOT NULL,
  ORDDAT  DATE           NOT NULL,
  ORDAMT  DECIMAL(11,2)  NOT NULL DEFAULT 0,
  ORDSTS  CHAR(1)        NOT NULL DEFAULT 'O',
  PRIMARY KEY (ORDNUM)
);

CREATE INDEX PRODLIB.ORDERS_CUS_DATE
    ON PRODLIB.ORDERS (ORDCUS, ORDDAT);

CREATE VIEW PRODLIB.OPEN_ORDERS AS
  SELECT * FROM PRODLIB.ORDERS WHERE ORDSTS = 'O';

The correspondences are direct: physical file → table, keyed logical file → index, logical file with selection → view.

What genuinely differs

This is not a matter of taste. There are three concrete differences.

Constraints. SQL lets you declare primary keys, foreign keys, uniqueness and validity conditions, and the database enforces them against anyone who writes: old program, new program, ODBC connection. In DDS those rules live in the programs, and hold as long as everybody goes through the programs.

Types, and when they are checked. DDS has date, time and timestamp too (types L, T and Z), but many files keep dates in numeric fields, like the 7P 0 above, and a 7P 0 can hold the 31st of February, a DATE column cannot. Then there is a difference affecting every type: IBM explains that a physical file does not enforce data types as strongly as an SQL table, and that a program writing at record level can put invalid data into a packed field; in an SQL table such a write is rejected.

Note

there is a practical difference that surprises people converting. A DDS file has ten-character names, and SQL tables allow long names while keeping a short system name for compatibility. Long and short coexist (FOR SYSTEM NAME declares it explicitly) and RPG programs go on using the short one without noticing anything.

How it is read, which is a separate choice again

Describing data one way or the other is independent of how a program reads it. The two routes coexist even inside the same program.

Native record-at-a-time. CHAIN, READ, SETLL, READE: one record at a time following a key. It is fast when you know exactly which record you need, and it is how all the historic code is written.

Embedded SQL. You declare what you want and the database decides how to get it. It is far better when working over sets — totals, groupings, joins, complex filters — and there record-at-a-time is not competitive, because a join done by hand in RPG is a loop inside a loop.

Tip

the rule of thumb that holds is: one record by key, native; more than one record together, or data coming from several files, SQL. A program reading three thousand records to add them up is doing in RPG a job the database does better, and the gap widens with the file.

What to do with what exists

The short answer is: do not convert for the sake of converting.

The code does not need touching. An RPG program reading ORDERS keeps working without recompiling if ORDERS becomes an SQL table with the same record format level identifier: IBM's modernisation Redbook says to check it after conversion. Converting the definition is not rewriting the application, and the starting SQL is generated by ACS (Schemas, "Generate SQL") or by the GENERATE_SQL service.

New files are made in SQL. It is the zero-cost choice: from today on, what gets created is created in DDL.

Indexes, yes, straight away. There is no reason to describe a new key-only logical file in DDS: CREATE INDEX does the same thing, and the system itself says which indexes it would like.

SELECT TABLE_NAME, KEY_COLUMNS_ADVISED, TIMES_ADVISED, MTI_USED
  FROM QSYS2.SYSIXADV
 WHERE TABLE_SCHEMA = 'PRODLIB'
 ORDER BY MTI_USED DESC, TIMES_ADVISED DESC

Do not create them all. The advisor reasons one query at a time: it does not know which indexes you already have, how many writes that table takes, nor that half the advice are variants of the same thing. Every index has to be maintained on every INSERT, UPDATE and DELETE, and a table loaded with useless indexes slows the overnight batches down, with the symptom appearing weeks later, far from whoever created them. An index on (A, B, C) already covers lookups by (A) and (A, B), so three pieces of advice are often a single index. How to read the advice and how to consolidate it is in the recipe finding the indexes the system suggests.

Warning

converting an existing file from DDS to SQL is not a neutral operation and wants a plan. Logical files built on top have to be recreated as indexes or views, programs have to be recompiled if the level identifier changes, and data in the physical file today may not fit the table: invalid packed decimals, which the physical file accepted, the table rejects. IBM provides SYSTOOLS.VALIDATE_DATA_FILE to find them first, with record number and field. Discover it on test, not in production.

Sources

Back to the guide index

← Back to blog

Comments

No comments yet. Be the first to comment!

You need an account to comment. Log in · Sign up