The seed for this post came from a conversation I had with one of my work colleagues. He complained that even though he could give the columns (fields) in a DDL (SQL) tables names longer than ten characters he found that it was hard to use these names in programs, especially those using printer or display files.
He is not the first person who had made this observation to me. Over the time I have written this web site others have made the same observation.
Let me show what I shared with him so that he could easily overcome this perceived shortcoming.
We need to start with a DDL table, with long column names:
01 CREATE TABLE MYLIB.MYTABLE ( 02 FIRST_COLUMN CHAR(3) NOT NULL, 03 SECOND_COLUMN VARCHAR(20), 04 THIRD_COLUMN DECIMAL(10,2), 05 FOURTH_COLUMN VARCHAR(50) 06 ) ; |
After I have created the table I use the SYSCOLUMNS Db2 of i view to see what names have been automatically picked as the "system" names, I call them "short" names.
SELECT SYSTEM_COLUMN_NAME,COLUMN_NAME FROM QSYS2.SYSCOLUMNS WHERE TABLE_NAME = 'MYTABLE' AND TABLE_SCHEMA = 'MYLIB' SYSTEM_COLUMN_NAME COLUMN_NAME FIRST00001 FIRST_COLUMN SECON00001 SECOND_COLUMN THIRD00001 THIRD_COLUMN FOURT00001 FOURTH_COLUMN |
I have to agree with my colleague that those a pretty nasty "short" names for the columns.
My colleague had asked specifically about the "long" names with display and printer files.
I need to use the "short" names in both files. Below is how I would define them in a subfile record format.
01 A R SFL01 SFL 02 A Z1RRN 5S 0H 03 A Z1OPT 1A B 2 2 04 A FIRST00001R O 2 4 05 A SECON00001R O 2 8 06 A THIRD00001R O 2 29EDTCDE(J) 07 A FOURT00001R H |
Those of you familiar with printer files will recognize this as a printer file record format.
01 A REF(MYTABLE) 02 A R PRINT 03 A FIRST00001R 1SPACEB(001) 04 A SECON00001R +1 05 A THIRD00001R +1EDTCDE(J) 06 A FOURT00001R +1 |
I created a very simple RPG program, and this is part of it.
01 **free 02 dcl-ds Data extname('MYTABLE') qualified dim(9999) 03 end-ds ; 04 dcl-f TESTDSPF workstn indds(Dspf) sfile(SFL01:d_Z1RRN) prefix(d_) ; 05 dcl-f TESTPRTF printer prefix(p_) ; |
Line 1: Let my RPG be free.
Lines 2 and 3: All of the programs I write now use SQL to get the data from the tables/files. As I would be using a multiple row fetch to get the data from the table, I need a data structure array for the columns I will fetch. Rather than define the subfields within the program I have defined it as externally defined using the table itself.
Line 4: This is the file definition for the display file. The only reason I have used the PREFIX keyword is to ensure that in the compile listing all the fields from the display file will start d_.
Line 5: Same is true of the file definition for the printer. By using the PREFIX all printer file fields will start p_.
What does the compile listing show?
dcl-ds Data extname('MYTABLE') qualified dim(9999) end-ds ; *-------------------------------------------------- * Data structure . . . . : DATA * External format . . . : MYTABLE : MYLIB/MYTABLE *-------------------------------------------------- <---------------------- Source Specifications ------ ....1....+....2....+....3....+....4....+....5....+.. D FIRST00001 3A D SECON00001 20A VARYING D THIRD00001 10P 2 D FOURT00001 50A VARYING O u t p u t B u f f e r P o s i t i o n s Statement Start End Field or Constant Number Pos Pos 4000002 1 5 D_Z1RRN 4000003 6 6 D_Z1OPT 4000004 7 9 D_FIRST00001 4000005 10 29 D_SECON00001 4000006 30 39 D_THIRD00001 4000007 40 89 D_FOURT00001 6000002 1 3 P_FIRST00001 6000003 4 23 P_SECON00001 6000004 24 33 P_THIRD00001 6000005 34 83 P_FOURT00001 |
All of the fields based upon the columns in my table use the "short" names. This is what is driving my colleague to only use ten long column names.
The solution is just five characters long, ALIAS. All I need to do is add the that keyword to my data structure array definition and to the definition of my two files.
02 dcl-ds Data extname('MYTABLE') qualified alias dim(9999) 03 end-ds ; 04 dcl-f TESTDSPF workstn indds(Dspf) sfile(SFL01:d_Z1RRN) prefix(d_) alias ; 05 dcl-f TESTPRTF printer alias prefix(p_) ; |
After compiling this program when I look in the compile listing I can see that the ALIAS has allowed the "long" names of the columns to be used for the data structure's subfields and the display and printer file's fields.
dcl-ds Data extname('MYTABLE') qualified alias dim(9999) end-ds ; *-------------------------------------------------- * Data structure . . . . : DATA * External format . . . : MYTABLE : MYLIB/MYTABLE *-------------------------------------------------- <---------------------- Source Specifications ------ ....1....+....2....+....3....+....4....+....5....+.. D FIRST_COLUMN 3A D SECOND_COLUMN 20A VARYING D THIRD_COLUMN 10P 2 D FOURTH_COLUMN 50A VARYING O u t p u t B u f f e r P o s i t i o n s Statement Start End Field or Constant Number Pos Pos 4000002 1 5 D_Z1RRN 4000003 6 6 D_Z1OPT 4000004 7 9 D_FIRST_COLUMN 4000005 10 29 D_SECOND_COLUMN 4000006 30 39 D_THIRD_COLUMN 4000007 40 89 D_FOURTH_COLUMN 6000002 1 3 P_FIRST_COLUMN 6000003 4 23 P_SECOND_COLUMN 6000004 24 33 P_THIRD_COLUMN 6000005 34 83 P_FOURTH_COLUMN |
Yes, it is that simple. There is no need to change the files, just the RPG program using them.
Now my colleague can go back to making column names in his tables that are meaningful, rather than abbreviating the names to just ten long.
This article was written for IBM i 7.3, and should work for 7.1 and later too.
Always very handy
ReplyDeleteSomething to try...
ReplyDeleteInstead of letting the system generate the short name, you can try the 'FOR' option in the DDL. This way you have the best of both worlds. And you get to keep the brain fresh by trying to come up with those short names that make sense. :)
CREATE TABLE MYLIB.MYTABLE (
FIRST_COLUMN For MyCol1 CHAR(3) NOT NULL,
SECOND_COLUMN For MyCol2 VARCHAR(20),
THIRD_COLUMN For MyCol3 DECIMAL(10,2),
FOURTH_COLUMN For MyCol4 VARCHAR(50)
) ;
That works very well for creating "good" short column names.
DeleteI have mentioned what you described in various posts before, for example here.
This works great for column names, however, keep in mind your still going to run into a potential problem when creating a SQL long table name (alternative name beyond 10 characters). There is an issue when using the system commands CPYF, MOVOBJ and CRTDUPOBJ which is irrespective and separate from using long column names. When using these system commands we are restricted to the 10 character system name equivalents. This in and of itself is not necessarily and issue but it does represent an issue when using those commands to copy, move or create a duplicate object from system FileName_A to FileName_B within the SAME library. The commands will fail because the alternative name (SQL long name beyond 10 characters) automatically attempts to carry over to File_B and of course duplicate names within the SAME library are not allowed. If copying to a different library we don't have that issue because we can have duplicate file system names and duplicate alternative names as long as they each resides in a different schema and recognized as such ny the system cross reference files.
ReplyDeleteThere are ways around this issue but it's just something to be cognizant of when using those system commands where SQL alternative names are assigned to tables.
Are you talking Table names? (Which can be more than ten long)
DeleteAs the long column name does not cause a problem if I use CRTDUPOBJ, MOVOBJ, or CPYF with the table/file in the example I gave above.
+1 on FOR 'system-name'. This adds great value to incremental modernization.
ReplyDeleteReal example: A need arose to replace old-style packed date/time fields in a DDS PF with DATE/TIME data types. While at it why not convert it to a DB2 table?
Solution: Refactor PF into a table whose name is the same (short). We could have used 'system-name' to yield a new long table name. We did not for reasons too numerous to discuss here.
Determine long names for all existing columns, employing FOR 'system-name' to identify the short names. Add new columns for DATE/TIME values (leave the old ones in place). Add PRIMARY KEY (use the new long name). Add LABELs and COMMENTs. Create the table. Populate it with existing data. Create all the DDS LFs (including one JOIN LF). Recompile all referencing code objects. We now have our table.
We identified code populating the old-style date/time fields and added *additional* code to populate the new columns. Subsequent refactoring will replace the old fields with new ones--eventually they can removed from the table entirely. Going forward new code can use the long names (via ALIAS keyword in RPG). Existing code can be refactored on your timetable and plan.
This DDS PF had 1/2 dozen LFs with ~115 referencing code objects. ALL recompiled with no change required. I actually did not believe what the IBM i was telling me when I first saw this. "No way can RPG just compile all these programs. Something will break."--this is what I told myself. Each program I tested though--a report, 5250 maintenance program, service program, etc.--all worked. I tested less than 10 and decided to just go for it. No post-move issues arose.
Naturally every data set (PF/LF) and the code it's married to are different. Some are easy to refactor. Some not so easy. Others are a nightmare. Some may never get done. YMMV.
I define both long and short column names and table names in the DDL. Then I can choose which I want to use in programming, which allows backwards compatibility for those programs I need to modernize the DB for, but not (yet) the program. BTW, seems to me that for DSPF's / PRTF's aliases work only when using REFFLD's in the DSPF/PRTF definitions, yes?
ReplyDeleteOr you can use the ALIAS keyword in the DSPF & PRTF.
Delete