Your SlideShare is downloading. ×
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Introducing your COBOL programs to DB2 version 8
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Introducing your COBOL programs to DB2 version 8

3,139

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
3,139
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
88
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Introducing your COBOL programs to DB2 version 8 David Churn DST Systems, Inc. 16 October 2008 • 09:00 – 10:00 Platform: DB2 for z/OS It is supposed to be easy to change your existing programs from single row to multiple row fetch. There are some difficulties involved in this process especially when it is a COBOL program. This presentation will take you through the issues that have been encountered and how DST solved them. Coding examples and some suggested standards will be included. 1
  • 2. The Five Points • SQL in COBOL • Array handling • Using GET DIAGNOSTICS • Unit of work • Mixing in other SQL features Greetings! 2 There are other good feature in v8 that will speed performance but do not impact how COBOL programs are written. Features like scalar full-SELECT and common table expressions have an impact on the program’s SQL only. They will not be covered in this presentation. 2
  • 3. Disclaimer • The information is presented “as is” without any warranty either expressed or implied. The use of this information is the client’s responsibility. • All information in this presentation relates to DB2 Version 8 and COBOL version v3r4. • COBOL programs were developed on z/OS mainframe using TSO and ISPF. 3 3
  • 4. About DST Systems http://www.dstsystems.com • Leading provider of computer software solutions and services, NYSE listed – “DST” • Revenue $2.24 billion • 110 million+ shareowner accounts • 24,000 MIPS • 150 TB DASD • 145,000 workstations • 462,000 DB2 objects • Non-mainframe: 600 servers (DB2, Oracle, Sybase) with 2.3 million objects . 4 If you have ever invested in a mutual fund, have had a prescription filled, or are a cable or satellite television subscriber, you may have already had dealings with our company. DST Systems, Inc. is a publicly traded company (NYSE: DST) with headquarters in Kansas City, MO. Founded in 1969, it employs about 12,000 associates domestically and internationally. The three operating segments - Financial Services, Output Solutions and Customer Management - are further enhanced by DST’s advanced technology and e- commerce solutions. 4
  • 5. DST associate mix • Applications Development • Database Administrators • Database Consultants Developers Project Leaders Analysts Programmers DBA DB Consulting hundreds tens ones 5 Our development staff is heavily slanted toward application development. Most enhancements are coded by the applications area to provide new functionality. Application Developers code their own SQL and are responsible for checking the EXPLAIN information. DBAs assist with the enhancements and handle implementing changes to each production system’s database. They review new SQL and assist with designing indexes as needed. Database Consulting assists with SQL development on a project basis and assisting our trainers. One of our goals as Database Consultants is to pass along best coding practices to the developers. Database Consultants evaluate new features of DB2 and write the standards for DB2 and COBOL. 5
  • 6. SQL in COBOL This section gives an overview of the new features added to SQL in version 8 that impact how a COBOL program is written. The largest coding change comes from the new multiple row functions for SELECT and INSERT. 6
  • 7. DB2 v8 gives COBOL programs the ability to define larger fields and data inside the program. COBOL has a full size CURSOR name takes 3 lines using the ISPF editor on TSO. A full size character constant takes 546 l 7
  • 8. SQL continuation • Word/literal occupies column 72 • Next line has • Hyphen in column 7 • Spaces in 8 through 11 • Followed by remainder of word/literal • Character literal requires a quote 7 12 72 | | EXEC SQL INSERT INTO tbl(column1,colum - n2, column3, column4) VALUES ( 0123 - 45, ‘chara - ‘cter literal’) END-EXEC. 8 Even with only 60 characters on a line, it was a rare need to know these rules. With most DB2 object having m 8
  • 9. Binary Numbers – TRUNC(STD) • COMP, COMP-4 and USAGE BINARY are synonyms for truncating binary. • Truncation happens when field • Receives data from a MOVE • Arithmetic result • COMP-5 indicates no truncation. S9(4) COMP = -9999 to +9999 2 bytes S9(9) COMP = -999,999,999 to +999,999,999 4 bytes S9(4) COMP-5 = -32768 to +32767 2 bytes S9(9) COMP-5 = -2147483648 to +2147483647 4 bytes 9 The COBOL standard states that numeric fields must be truncated to their picture clause. This is sometimes referred to as the ‘odometer effect’. A two byte binary field can contain a minimum value of -32768 and a maximum of +32767. Because the field is defined as PIC S9(4) COMP, COBOL will limit them to 4 digits. DST standard; use COMP-5 for SMALLINT INTEGER VARCHAR lengths Null indicators Note: This applies when the COBOL compiler option TRUNC(STD) is set. It may apply for TRUNC(OPT). It does not apply with TRUNC(BIN). Consult the COBOL for zOS Programming Guide for more details. 9
  • 10. Largest numbers • Largest COBOL numeric picture • S9(31) COMP-3 • S9(1)V9(30) COMP-3 • z(30)9 • z,zzz,zzz,zzz,zzz,zzz,zzz,zzz,zzz,zzz,zz9 • Largest DB2 numeric • DECIMAL(31,0) • COBOL and DB2 math use 31 digits of precision • Precompiler parm DEC(31) • Compiler parm ARITH(EXTEND) 10 Without using the parms above, the largest COBOL numeric field can be 18 digits and the largest DB2 numeric field can be 15 digits. These smaller parms are faster than the 31 digits parms. The smaller compiler parms are Precompiler DEC(15) Compiler ARITH(COMPAT) If the program has a multi-operation math statement, then the compiler parms also specify the number of digits used for the intermediate results. 10
  • 11. Definitions • Array: A group of things arranged in a structured way. In COBOL, a WORKING-STORAGE field with OCCURS. • Copybook: predefined COBOL instructions that can be added to a program with either the COPY or EXEC SQL INCLUDE instructions. • Host Variable: COBOL field, in either WORKING-STORAGE or LOCAL-STORAGE • Host Variable Array: An array that is used in SQL as a host variable. • Restartable: Functionality in a program that lets it start over after an error situation. • Unit of Work: point where one piece of work is considered done. 11 These define the terms used in this presentation which can have different meaning in another context. For this presentation, table means a DB2 table. 11
  • 12. Multi-row Fetch/Insert • Fetch or Insert up to 32,767 rows in one statement • Fewer calls to DB2 • Use arrays instead of fields • Requires more memory • Limit the number returned for CICS • Request the same or fewer rows than defined in the OCCURS, but not more. • Increases program complexity • Additional perform loop level • More error handling code 12 Our current production COBOL compiler v3r4 expanded the maximum size of an 01 level item to 128Mb while leaving the total size of all working-storage at 128Mb. CICS programs need to manage the amount of memory they are going to use. For batch programs DST defines all columns in a table with the same number of occurrences for each column and null indicator. If a CICS program is only going to use a few columns from a table with hundreds of columns, then we examine how to reduce the extra unused memory. 12
  • 13. If the program requests 100 rows but DB2 returns only 10 rows, the program performs like it requested 10 rows. Some knowledge of the data is needed to evaluate whether to use multi-row FETCH. recommendation = Use Multi-row fetch when a cursor typically returns 4 or more rows. 13
  • 14. Multi-row Fetch SQL syntax Cursor Definition Example DECLARE MEANINGFUL_NAME CURSOR WITH ROWSET POSITIONING FOR SELECT … Fetch Example FETCH NEXT ROWSET FROM MEANINGFUL_NAME FOR numeric literal ROWS INTO :hv-array1, :hv-array2 … OR FETCH NEXT ROWSET FROM MEANINGFUL_NAME FOR :hv ROWS INTO :hv-array1, :hv-array2 … 14 When the number of rows is not given multi-row FETCH defaults to 1 row. A program cannot tell DB2 which occurrences to populate in a FETCH. If the program fetches 20 rows in 14
  • 15. Recommend Multi-row Fetch • More than 4 rows per fetch • Program is designed for multi-row FETCH • Driving cursor defined WITH HOLD • Fetch 100 rows • Process all rows • End unit of work (COMMIT) • Entire cursor process is within a single unit of work. • Open cursor • All rows processed completely • Close cursor • Start-up array loading cursors 15 Since coding for a multi-row fetch CURSOR is more complex than using a single row CURSOR, we evalu 15
  • 16. Avoid Multi-row Fetch • Added complexity without clear savings • Program does not have a clear unit of work • Burying multi-row functionality inside fetch routine OPEN *=same routine FETCH* UPDATE program PROCESS Check (1) (x) COMMIT Get more rows? FETCH* MR-FETCH Give row CLOSE 16 Fetch time is typically only a small part of the total program time. Even an 55% improvement of 10 seconds i Programs that have no clear Logical Unit of Work are more difficult to change. It may even be impossible to Multi-row SELECT works better when it is designed into the program from the beginning. Burying multi 16
  • 17. If the program requests 100 rows but DB2 returns only 10 rows, the program performs like it requested 10 rows. Some knowledge of the data is needed to evaluate whether to use multi-row INSERT. recommendation = Use Multi-row insert when a unit-of-work typically inserts 15 or more rows to a table. 17
  • 18. Multi-row Insert Syntax • Atomic (default) • Severe error (negative SQLCODE) rolls back entire INSERT • Stops on first error • Easier logic to reposition for restart EXEC SQL INSERT INTO table (column list) VALUES (value list, host variable arrays) FOR :hv ROWS ATOMIC END-EXEC 18 When a program performs a multi-row INSERT using the ATOMIC option, DB2 behaves according to the •An error rolls back the entire INSERT but only the INSERT. •DB2 stops checking for errors after it finds the first failed row. There will be only 1 error returned. •A COBOL program is easier to code restart and reposition logic using the ATOMIC option. 18
  • 19. Multi-row Insert Syntax • Not Atomic • No rollback • Does not stop • Restarting can be difficult • New SQLCODEs and SQLSTATEs EXEC SQL INSERT INTO table (column list) VALUES (value list, host variable arrays) FOR :hv ROWS NOT ATOMIC CONTINUE ON SQLEXCEPTION END-EXEC 19 When a program performs a multi-row INSERT using the NOT ATOMIC option, DB2 behaves according to •DB2 can get multiple errors on the INSERT. The program needs to use GET DIAGNOSTICS to report the e •The code is more complex to restart a program using the NOT ATOMIC option. •This type of INSERT is ideal for a program where the only response to an error is to save the row, skip over i DB2 will return one of the four SQLCODEs when a program does a multiple row fetch. To determine the ind •All successful – SQLCODE = +0, SQLSTATE = 00000 •All successful but warnings – SQLCODE = +252, SQLSTATE = 01659 •At least one (but not all) failed –SQLCODE = -253, SQLSTATE = 22529 •All failed – SQLCODE = -254, SQLSTATE = 22530 19
  • 20. Recommend Multi-row Insert • More than 15 rows per insert • Many Inserts on single table • Inserting is the only process in the program • Like load utility without the outage • Many inserts within a unit of work 20 recommendation = Use multi-row insert when the primary purpose of the program is to insert--especially w Using ATOMIC or NOT ATOMIC options are based on the application logic. To date most have been ATOM 20
  • 21. Avoid Multi-row Insert • Multiple tables are changed • If some/all rows fail (ATOMIC), how does the program back out the other changes related to those rows? • If some rows fail (NOT ATOMIC), how does the program back out only the changes related to the failed rows? • Do not delay commits for the purpose of building up a host variable array. 21 The program should change other tables after the multi-row insert. So when the program is doing ATOMIC in changes only to successful rows. All this logic will add time to the coding and testing of the program. Artificially delaying commits defeats the purpose of commit checks—reducing rollback time and contention w 21
  • 22. Array Handling Multi-row FETCH and INSERT It is not about the SQL. It is about the COBOL! 22
  • 23. Host Variable Arrays • SQL references arrays of elements 01 DCL-EMPLOYEE-20. 05 EMPLOYEE-ID PIC S9(5)COMP-3 OCCURS 20 TIMES. 05 COMMENT-TXT OCCURS 20 TIMES. 49 COMMENT-TXT-LEN PIC S9(4) COMP-5. 49 COMMENT-TXT-TEXT PIC X(255). • SQL cannot reference a group item array. 01 EMPLOYEE-TABLE. 03 DCL-EMPLOYEE-20 OCCURS 20 TIMES. 05 EMPLOYEE-ID PIC S9(5) COMP-3. 05 COMMENT-TXT. 49 COMMENT-TXT-LEN PIC S9(4) COMP-5. 49 COMMENT-TXT-TEXT PIC X(255). 23 DB2 requires that an array is created for each column used in a SELECT. COBOL has been optimized to proc instructions than the second example. If many fields are defined in the group item (01) then the performance DST uses standardized host variable arrays that are created for multi-row functions. If the copybook is used in Other OCCURS sizes can be used but need justification. 23
  • 24. New Multi-row copybooks • DCLGEN does not build multi-row copybooks. • May require two copy books • WHERE clause references single column definitions • FETCH INTO references host variable arrays • Remember group item lists 24 The standard DCLGEN process included with SPUFI will not generate a table definition where the COBOL fields have the OCCURS clause. Either someone will have to change the generated copybook or someone will need to write something produce the fields to be used in a multi-row function. There may be a need to have both a single row and a multi-row versions of the copybook. SQL WHERE clauses can only reference one type of array. SQL cannot reference one occurrence of an array item. The only COBOL can pass an array is for an IN list. The array has to be defined as follows. Each elementary item is required to have a name even if the value is constant. 01 HV-CUST-INITIALS. 05 HV-INIT1-TX PIC X(3) VALUE SPACE. 05 HV-INIT2-TX PIC X(3) VALUE SPACE. 05 HV-INIT3-TX PIC X(3) VALUE SPACE. 05 HV-INIT4-TX PIC X(3) VALUE SPACE. 05 HV-INIT5-TX PIC X(3) VALUE SPACE. 05 HV-INIT6-TX PIC X(3) VALUE SPACE. PROCEDURE DIVISION. 24 …
  • 25. Array Handling Restrictions • Use subscripts to access one row from multiple tables • COMP vs. COMP-5 (COMP is faster) • Updating many indexes is slower than one subscript • Cannot use variable length arrays • OCCURS DEPENDING ON rejected by precompiler and coprocessor • SEARCH and SEARCH ALL will search entire array • Must be visible to the SQL precompiler. • Cannot use COPY … REPLACING • Initializing groups of arrays is slower than initializing one array with many fields. 25 There are many different ways to process COBOL arrays. We found that using subscripts was the best way to handle the occurrences with many host variable arrays. We also found that all host variable arrays need to be fixed length even though it makes the SEARCH or SEARCH ALL statements process the entire array. It is faster for COBOL to access an array with an index instead of a subscript. If there are multiple columns inside host variable arrays, then the faster speed is lost to updating multiple indexes instead of one subscript. A program will compile using the same name for multiple indexes as long as it does not reference the name. A program will not compile using an INDEXED BY clause reference another index. Host variable arrays must be visible to the SQL processor. For programs using the precomiler, host variable arrays must be defined in the program or included in the program with EXEC SQL INCLUDE. Programs using the coprocessor can use the COPY and could change the number of rows using the following statement. COPY DATYP REPLACING ==OCCURS 20== BY ==OCCURS 40==. There are fewer Assembler instructions created for initializing one array with multiple fields instead of initializing many host variable arrays. 25
  • 26. COBOL Array Handling • SEARCH WHEN clause is limited to one element SEARCH EMPLOYEE-ID [will vary its index] AT END (at end code) WHEN EMPLOYEE-ID (EMPLOYEE-IDX) = ws-employee-id AND WORK-DTE (WORK-DTE-IDX) = ws-work-dte (when found code) END-SEARCH • WORK-DTE-IDX will not be incremented by the SEARCH verb. • The program compiles successfully, but will produce incorrect results if it requires automatic incrementing. 26 When a program has fetched data into host variable arrays and there is a multiple column key, the program ca A custom routine must be coded to find the right row. 26
  • 27. Multi-row Fetch data • When fetched, null columns do not update the column host variable – only the null indicator. ID Name Account Null 1st 8 row FETCH 1 9 David Churn Jim Smith 100 135 0 SQLCODE=0 SQLSTATE=00000 2 David Churn 10 John Smith 200 0 -1 SQLERRD(3) = 8 3 Henry Jones 46 11 Harry Thompson 357 0 2nd 8 row FETCH 12 Kathy Winters 4 Henry Jones 579 24680 0 SQLCODE=+100 5 Henry Jones 25000 0 SQLSTATE=02000 6 Jean Smith 76 0 SQLERRD(3)=4 7 Jean Smith 234 0 Last 4 rows are carry over from the 8 Jim Smith 1000 0 last FETCH 27 When working with nullable columns it is still important to define and check the null indicator. It would not be good to mix up John Smith’s money with David Churn’s account. 27
  • 28. Moving VARCHAR • For VARCHAR columns, move only the bytes that DB2 populated. • Move source (start,length) to destination MOVE text-field OF DCL-xxx-Mnnn (1: text-len OF DCL-XXX-Mnnn) TO • Becomes move source (sub) (start:length) to … MOVE text-field OF DCL-xxx-Mnnn (sub) (1: text-len OF DCL-XXX-Mnnn (sub) ) TO 28 Like null indicators, a program should move variable length fields for the length that DB2 returned. Subscript 28
  • 29. Process loops Old New 2000-PROCESS. 2000-PROCESS. PERFORM 2100-OPEN-CURSOR PERFORM 2100-OPEN-CURSOR PERFORM 2200-FETCH PERFORM UNTIL END-OF-CUR PERFORM UNTIL END-OF-CUR PERFORM 2200-FETCH ADD +1 TO FETCH-COUNT PERFORM 6000-WRITE VARYING PERFORM 6000-WRITE EMPLOYEE-SUB FROM +1 by +1 PERFORM 2200-FETCH UNTIL EMPLOYEE-SUB > END-PERFORM SQLERRD(3) PERFORM 2300-CLOSE-CURSOR ADD SQLERRD(3) TO FETCH-COUNT END-PERFORM PERFORM 9600-CHECK-UOW PERFORM 2300-CLOSE-CURSOR PERFORM 9000-READ PERFORM 9600-CHECK-UOW PERFORM 9000-READ 29 There are two changes to the potential program’s logic. 1) The priming FETCH is eliminated. 2) The 6000 This New example is not the best way to actually code it but is a good way to illustrate the change. In actual c 29
  • 30. Multi-row Fetch Caution • Non-rowset fetch puts ID Name data in first occurrence 1 David Fetch 3 rows • Mixing rowset and non- rowset fetchs gives 2 Gordon Fetch next unobvious results • Fetch more rows than 3 Jim Fetch 3 rows array occurrences 4 Mike Fetch 3 rows gives SQLCODE=+354 SQLSTATE=01668 5 Suresh 6 Thomas 30 When a program only uses multi-row fetch, rows are returned in a predictable fashion. The first Fetch 3 rows returns David, Gordon, and Jim. The second Fetch 3 rows returns Mike, Suresh, and Thomas. When a program adds a FETCH NEXT in between the Fetch 3 rows it give the following results. The first Fetch 3 rows returns David, Gordon, and Jim. The Fetch next returns Gordon. The second Fetch 3 rows returns Jim, Mike, and Suresh. This could cause the program to process the rows for Gordon and Jim twice. 30
  • 31. Using Where Current • UPDATE/DELETE… WHERE CURRENT... • Changes behavior based on last FETCH • UPDATE/DELETE WHERE CURRENT OF..FOR ROW x OF ROWSET • Update/Deletes a specific row of the rowset • Restartable cursors must have an ORDER BY • Cursors with ORDER BY cannot use WHERE CURRENT 31 If positioned on a single row (previous fetch was regular), then DB2 updates/deletes single row If positioned on a rowset (previous fetch was ROWSET … FOR n ROWS), then DB2 updates/deletes entire set of rows If you mix and match row and rowset fetches in your program, the program could have DB2 accidentally update or delete a rowset instead of a single row! 31
  • 32. Multi-row Insert Feature • A non-array column has the same value for ALL rows • In the following example, ID and name are simple host variables, not host variable arrays. 05 HV-ID PIC S9(7) COMP-3 VALUE ZERO. 05 HVA-ACCOUNT PIC S9(15) COMP-3 OCCURS 100 TIMES VALUE ZERO. 05 HV-NAME PIC X(100) VALUE SPACES. 05 HVA-AMOUNT PIC S9(11)V99 COMP-3 OCCURS 100 TIMES VALUE ZERO. INSERT INTO TABLE (id, account, name, amount) VALUES (:hv-id, :hva-account, :hv-name, :hva-amount) FOR :hv-num-rows ROWS ATOMIC 32 Multi-row INSERTs do not have to use host variable arrays for every column. If the value for all rows will be the same, then the program could use a non-array COBOL field to save the one value. Like the multi-row FETCH, DB2 always starts with the first occurrence of a host variable array. There is no way to tell DB2 to start with any other occurrence. The program should always set the number of rows inserted. If it tells DB2 insert 4 rows from an array of 8 rows, the first 4 occurrences will be used, the remaining 4 occurrences will be ignored. 32
  • 33. Multi-row Insert Caution • Formatting everything • Null indicators • VARCHAR lengths • Number of rows in INSERT • Error handling in loops • Group moves to or from the host variable arrays 33 Like a single INSERT, verify that all the indicators and lengths are set right in the host variable arrays. The p There will be more logic to process errors from inserting multiple rows. Displaying information from the SQL If programs usually move a row’s information in one group move, they will have to change to individual mov 33
  • 34. Using GET DIAGNOSTICS What happened?!? 34
  • 35. GET DIAGNOSTICS • EXEC SQL GET DIAGNOSTICS identifies • number of messages • each message’s SQLCODE and SQLSTATE • row number in the host variable array • Calling GET DIAGNOSTICS returns an SQLCODE and refreshes the SQLCA 35 It is possible to get multiple warnings as well as an error on one row. Whenever a program uses a multi-row fetch or multi-row insert, it should also use GET DIAGNOSTICS. 35
  • 36. Multi-row Fetch Results • Success, SQLCODE=0, SQLSTATE=00000 • 1 serious error • “regular” message, SQLCODE=negative • GET DIAGNOSTICS will repeat error • One to many warnings • Overall warning - SQLCODE=+354, SQLSTATE=01668 • Multiple warning conditions • GET DIAGNOSTICS needed to expose messages • Check SQLERRD(3) for rows returned 36 If the program just reports on information in the SQLCA, then it may be hard to determine what happened. SQLCODE=+354, SQLSTATE=01668 A ROWSET FETCH STATEMENT RETURNED ONE OR MORE ROWS OF DATA, WITH ONE OR MORE BIND CON Explanation: A rowset FETCH statement returned one or more rows of data, however, one or more bind out processing error condit All of the following conditions will cause a multi-row FETCH to return an SQLCODE=+354 •Nulls were bypassed for an aggregate function for row 3, 1 message results •Date was adjusted occurs for row 9, 1 message results •rows 3, 9, and 45 have nulls in a column but the program does not have a null indicator. 1 message fo •6 errors result! 3 missing null-indicator, 1 nulls bypassed, 1 date adjusted and (1) 01668 (the program 36
  • 37. For Multi-row Insert • ATOMIC • Error handling does not change • NOT ATOMIC CONTINUE ON SQLEXCEPTION • SQLCODE=+252, SQLSTATE=01659, success with warnings • SQLCODE=-253, SQLSTATE=22529, one or more rows in error • SQLCODE=-254, SQLSTATE=22530, all rows failed • EXEC SQL GET DIAGNOSTICS to see the results for each failed row 37 Whether the program gets multiple errors depends on the atomicity of the INSERT. A program can get one error with an ATOMIC multi-row INSERT. A program can get multiple errors with a NOT ATOMIC multi-row INSERT. The SQLCODE passed back in the SQLCA is as useful as the one for multi-row FETCH. 37
  • 38. GET DIAGNOSTICS • How many errors? EXEC SQL GET DIAGNOSTICS :hv1 = NUMBER ,:hv2 = DB2_LAST_ROW ,:hv3 = MORE END-EXEC. • Specific condition information EXEC SQL GET DIAGNOSTICS CONDITION 1 (or :hv) :GD-RETURNED-SQLSTATE = RETURNED_SQLSTATE , :GD-DB2-RETURNED-SQLCODE = DB2_RETURNED_SQLCODE , :GD-DB2-REASON-CODE = DB2_REASON_CODE , :GD-DB2-ROW-NUMBER = DB2_ROW_NUMBER END-EXEC. 38 GET DIAGNOSTICS can return general information about errors, or information about a specific error. This specifics on each error. Unlike DSNTIAR this is another call to DB2 and should use SQLCODE checks after These are the options that are useful when determining how many errors are present. •NUMBER returns an integer – the number of conditions identified. •DB2_LAST_ROW returns an integer – it will contain +100 if the last operation was a multi-row fetch that re •MORE returns a Y/N indicator where Y means there was more error information available than could be retu Specifics •The program should use a perform loop to acquire all of the error information. •This statement acquires the sqlstate, sqlcode, reason code (sub reason) and row number associated with a spe •The program can hard code a condition number or can use a host variable. 38
  • 39. DST Usage • Copybooks • WORKING-STORAGE or LOCAL-STORAGE (copy in the notes) • PROCEDURE DIVISION • PERFORM 9970-MR-DIAGNOSTICS 39 01 WS00730 SYNC. 05 GET-DIAGNOSTICS-SQLSTATE PIC X(5) VALUE ZEROS. 05 GD-TOO-MANY-ERRORS PIC X VALUE 'N'. 88 DB2-TOO-MANY-ERRORS VALUE 'Y'. 05 LAST-ROW-SQLCODE PIC S9(9) COMP-5 VALUE ZERO. 88 LAST-ROW-FETCHED VALUE +100. 05 NUM-ERROR-INFO PIC S9(4) COMP VALUE ZERO. 05 ROW-ERROR-INFO OCCURS 500 TIMES. *500 should be sufficient for 100 fetch/insert (subject * To change) 10 ROW-SQLCODE PIC S9(9) COMP-5 VALUE ZERO. 10 ROW-REASON-CDE PIC S9(9) COMP-5 VALUE ZERO. 10 ROW-SQLSTATE PIC X(5) VALUE ZEROS. 10 ROW-NUMBER PIC S9(5) COMP-3 VALUE ZERO. * TEMP WORKING VARIABLES 05 DB2-NUMBER-OF-ERRORS PIC S9(9) COMP-5 VALUE ZERO. 05 DB2-RETURNED-SQLCODE PIC S9(9) COMP-5 VALUE ZERO. 05 DB2-REASON-CODE PIC S9(9) COMP-5 VALUE ZERO. 05 DB2-RETURNED-SQLSTATE PIC X(5) VALUE SPACES. 05 DB2-ROW-NUMBER PIC S9(31) COMP-3 VALUE ZERO. 05 DB2-CONDITION-NUMBER PIC S9(4) COMP-5 VALUE ZERO. 39
  • 40. * THIS MACRO IS USED FOR EXEC SQL GET DIAGNOSTICS ERROR * PROCESSING. * * PROGRAM SHOULD PERFORM 9970-MR-DIAGNOSTICS AFTER ANY ZC0068 logic * MULTI-ROW EXEC SQL STATEMENT RETURNS AN ERROR. * • Issues GET DIAGNOSTICS to obtain 9970-MR-DIAGNOSTICS. • The number of conditions MOVE ZERO TO NUM-ERROR-INFO OF WS00730. • The previous statement’s sqlstate EXEC SQL • Whether more errors occurred than could be GET DIAGNOSTICS (copybook limit Is 500 errors) reported :WS00730.DB2-NUMBER-OF-ERRORS =error’s • Performs a loop to obtain each NUMBER • SQLCODE , :WS00730.LAST-ROW-INDICATOR = DB2_LAST_ROW • SQLSTATE , :WS00730.GD-TOO-MANY-ERRORS = MORE • Return code END-EXEC. • Row number • Populates the array of error information within the MOVE SQLSTATE TO GET-DIAGNOSTICS-SQLSTATE OF WS00730 WS00730C copybook IF GET-DIAGNOSTICS-SQLSTATE OF WS00730 = ZEROS 40 * LIMIT RETURNED ERRORS TO 500. IF DB2-NUMBER-OF-ERRORS > +500 SET DB2-TOO-MANY-ERRORS OF WS00730 TO TRUE MOVE +500 TO DB2-NUMBER-OF-ERRORS OF WS00730 END-IF * DB2 BUILDS THE ERROR/CONDITION INFORMATION IN REVERSE ORDER * SO WE WILL BUILD OUR LIST OF INFORMATION BACKWARDS * SO THE ERRORS APPEAR IN THE ORDER THEY OCCURRED. PERFORM VARYING DB2-CONDITION-NUMBER OF WS00730 FROM DB2-NUMBER-OF-ERRORS OF WS00730 BY -1 UNTIL DB2-CONDITION-NUMBER < 1 OR SQLSTATE NOT = ZEROS EXEC SQL GET DIAGNOSTICS CONDITION :WS00730.DB2-CONDITION-NUMBER :WS00730.DB2-RETURNED-SQLSTATE = RETURNED_SQLSTATE ,:WS00730.DB2-RETURNED-SQLCODE = DB2_RETURNED_SQLCODE ,:WS00730.DB2-REASON-CODE = DB2_REASON_CODE ,:WS00730.DB2-ROW-NUMBER = DB2_ROW_NUMBER END-EXEC MOVE SQLSTATE TO GET-DIAGNOSTICS-SQLSTATE OF WS00730 40
  • 41. Sample Program Logic • Design a process to handle the messages. • Consider • Can the program continue? • What has been rolled back? • Multi-row FETCH • Multi-row INSERT • Atomic vs. Not Atomic • Are other processes dependent on this data? • Sample code to display gathered messages 41 This logic will display the errors gathered from the include book code. Sample DISPLAY loop PERFORM VARYING DB2-CONDITION-NUMBER OF WS00730 FROM +1 BY +1 UNTIL DB2-CONDITION-NUMBER OF WS00730 > NUM-ERROR-INFO OF WS00730 DISPLAY 'ROW NUMBER : ' ROW-NUMBER OF WS00730 (DB2-CONDITION-NUMBER OF WS00730) DISPLAY 'SQLSTATE : ' ROW-SQLSTATE OF WS00730 (DB2-CONDITION-NUMBER OF WS00730) DISPLAY 'SQLCODE : ' ROW-SQLCODE OF WS00730 (DB2-CONDITION-NUMBER OF WS00730) DISPLAY 'REASON-CDE : ' ROW-REASON-CDE OF WS00730 (DB2-CONDITION-NUMBER OF WS00730) DISPLAY 'ROW CONTENTS : ' UPON CONSOLE (put DISPLAY OF HOST VARIABLE ARRAY CONTENT here) END-PERFORM 41
  • 42. Unit of work 42
  • 43. Restartability • Why restart? DB2 rollback costs twice as much as the actual change (insert, update, or delete) • Restart concept • Where does the unit of work begin and end • Determine what triggers an end to a unit of work. • Next row from driving cursor • Change in control break field value • End of file condition • Must be designed into the program • Do other changes COMMIT before multi-row INSERT? • How does the program reposition during restart? 43 Maintainable units of work do not just happen. The associate writing the program has to figure out where they When the program does not have an apparent unit of work, it is difficult to enhance the program. It may be im If you cannot identify the beginning and ending of the Unit Of Work, you cannot “sneak” in a multi-row opera If a Unit of Work ends before the program completes a multi-row insert, the insert will become part of If a Unit of Work ends before the program completely processes all the rows fetched from a multi- 43
  • 44. Mass Inserts Instead of Try {Priming Read} {Priming READ} PERFORM UNTIL EOF PERFORM UNTIL EOF MOVE fields MOVE ZERO TO WS-NUMBER-TO-INSERT INSERT PERFORM VARYING x FROM +1 BY +1 CHECK COMMIT UNTIL x > +100 OR EOF READ MOVE fields TO hv array (x) END-PERFORM. ADD +1 TO WS-NUMBER-TO-INSERT READ END-PERFORM IF WS-NUMBER-TO-INSERT > ZERO MR-INSERT CHECK COMMIT END-IF END-PERFORM. 44 If the program’s process is to insert rows into a table, then the program can COMMIT after filling a multiple r 44
  • 45. Multi-row FETCH within a UOW Instead of Try PERFORM UNTIL EOC PERFORM UNTIL EOC FETCH MR-FETCH Perform Process- MOVE SQLERRD(3) row TO rows-fetched PERFORM process-row END-PERFORM. VARYING x FROM +1 BY +1 CHECK COMMIT UNTIL x > rows-fetched END-PERFORM CHECK COMMIT 45 The program should not process more data than DB2 returned. Refer to new example. 45
  • 46. Mixing SQL features •INSERT within SELECT •SELECT INTO … ORDER BY … FETCH FIRST •SEQUENCE objects •XML 46
  • 47. Select from Insert • Fewer DB2 calls • INSERT and SELECT errors are possible • Can be used with multi-row FETCH and INSERT • Does not work when an AFTER TRIGGER modifies the changed table. (SQLCODE=-989, SQLSTATE=560C3) Proceed with caution. SELECT col_id, insert_tsp, i_amt FROM FINAL TABLE ( INSERT INTO TRIGGER_TBL (insert_tsp, i_amt) VALUES(current timestamp, :i-amt) 47 Programs have the ability to get the assigned values of columns in the same statement where they are created. Some of the DB2 assigned columns that can be brought back to the program are identity column values, assigned sequence object values, and special register values (like CURRENT TIMESTAMP). When using this type of statement both INSERT errors and SELECT errors are possible, like the following examples. •Duplicate key from INSERT (SQLSTATE=23505) •Null without a null indicator from the SELECT (SQLSTATE=22002) Unfortunately, this statement is incompatible with some AFTER triggers. When an AFTER trigger, triggered Stored Procedure, or triggered UDF modifies the table that called it, the program gets an SQLCODE +100. Calling GET DIAGNOSTICS reveals the following error. The following text is from DB2 V8 Messages and Codes, pages 132-133 -989 AFTER TRIGGER trigger-name ATTEMPTED TO MODIFY A ROW IN TABLE table-name THAT WAS INSERTED BY AN INSERT STATEMENT WITHIN A SELECT STATEMENT Explanation: An INSERT statement was specified in the FROM clause of a SELECT statement of a subselect or a SELECT INTO statement, but the underlying target base table of the INSERT has an AFTER trigger defined which modifies the table being inserted. This is disallowed. System Action: The statement cannot be processed. 47
  • 48. Multi-row Select from Insert Build details (x) Open cursor Add rows Insert rows Fetch x rows (y) (1) Close cursor Audit rows (x) The number of rows and iterations should all be the same! 48 Whenever a program is going to do many inserts and it needs some of the assigned values, it can be written to execute a multi-row INSERT within a multi-row SELECT. To keep the logic simpler, keep the number of rows in the FETCH the same as the number of rows in the INSERT. An ORDER BY INPUT SEQUENCE clause should be used on the CURSOR definition to ensure the host variable array rows match. GET DIAGNOSTICS should also be used to look for INSERT errors with OPEN statement and SELECT errors on the FETCH. 48
  • 49. COBOL arrays example • Build all detail columns into host variable arrays • 3 calls to DB2 occ ID lmdt lmid col1 col2 col3 seq col4 1 100 ...01 AB U 11 77 2 MN Build 2 200 ...01 CD V 22 88 4 OP OPEN 3 300 ...02 EF W 33 99 6 QR FETCH 4 400 ...02 GH X 44 111 8 ST 5 500 ...03 IJ Y 55 222 10 UV CLOSE 6 600 ...03 KL Z 66 333 12 WX Audit ID lmdt lmid col1 col2 col3 seq col4 becomes 100 …01 AB U 11 77 2 MN 49 When to program needs to create a single image of a row it cannot use a group move from the host variable arrays. Instead individual moves from the host variable arrays need to move each column into a one row image. The color show when the individual host variable arrays are populated. Note; ID is an identity column, lmdt is populated with a CURRENT TIMESTAMP, and seq is given a value from a sequence object. 49
  • 50. CURSOR definition DECLARE NEW_EMPLOYEES CURSOR WITH ROWSET POSITIONING FOR SELECT EMPLOYEE_ID , WORK_DTE FROM FINAL TABLE ( INSERT INTO HOURS ( WORK_DTE, WORK_HOURS , APPROVAL_DTE ) VALUES ( CURRENT DATE , :DCLHOURS.WORK-HOURS, NULL ) FOR :WS-INSERT-QTY ROWS ATOMIC ) ORDER BY INPUT SEQUENCE 50 The slide show the actual SQL for populating an example row. Below is an example of the FETCH EXEC SQL FETCH NEXT ROWSET FROM NEW_EMPLOYEES FOR :WS-INSERT-QTY ROWS INTO :DCLHOURS.EMPLOYEE-ID , :DCLHOURS.WORK-DTE END-EXEC . EVALUATE SQLCODE WHEN ... WHEN OTHER GET DIAGNOSTICS needed END-EVALUATE 50
  • 51. SELECT INTO with ORDER BY • Replace CURSOR with single SELECT • Get first or last row from results • Continuing after “more than one” error gives unpredictable results (SQLCODE -811, SQLSTATE=21000) Use this Instead of this SELECT A.COL1 OPEN , A.COL2 FETCH one row INTO :WS-COL1 , :WS-COL2 CLOSE FROM TABLEA AS A WHERE … ORDER BY A.COL1 FETCH FIRST 1 ROW ONLY 51 Another handy feature introduced in version 8 is allowing an ORDER BY clause on a non-CURSOR SELECT. When used with the FETCH FIRST 1 ROW ONLY, a program does not need a CURSOR process to SELECT a specific row. Using “more-than-one-row” logic to return first row has always been unpredictable. In test results, we found that DB2 v7 would return the first row found—usually in the clustering sequence. In DB2 v8, the second row is returned. 51
  • 52. Sequence Objects work just like Identity columns but are not part of a single table. They can be used like an i those numbers. The syntax above shows how to get values from a sequence object without a SELECT, INSER A program can also return the just assigned value of an identity column by using the IDENTITY_VAL_LOCA 52
  • 53. XML • COBOL verbs • XML PARSE to read a document • XML GENERATE to write a document • DB2 processes and functions • XML extender • Save document in one column • Use document access definition file (DAD) • Parse into a relational table • Build XML document • Functions to build elements from columns • Better functionality in DB2 9 53 There are several choices for building and reading an XML document that relates to DB2 data. COBOL has its own built in function to parse an XML document and build an XML document from an array. DB2 has an automatic way to parse and build XML documents from table items. Programs can also call XML scalar functions on DB2 columns to return the data in XML format. It would take another presentation to cover these options adequately. There is also better functionality in DB2 9 to handle XML data. 53
  • 54. Conclusions • Longer names yield better descriptions • More COBOL complexity • Multi-row INSERT • Multi-row FETCH • Less COBOL complexity • SELECT from INSERT • SELECT INTO … ORDER BY … FETCH FIRST • New features • Sequence Objects • XML 54 Our COBOL programs have access to new features that improve performance. The multi-row functions improve performance while adding some complexity to our programs. The other features improve performance and make the program less complex. Most of the improvements make fewer trips between the program and DB2. DB2 version 8 provides new functionality that makes handling XML data easier and DB2 9 will make it even easier. 54
  • 55. Acknowledgements • Special thanks to Mike Todd 55 Special thanks to Mike Todd for providing access to his notes and permission to use the information. 55
  • 56. Session F14 Introducing your COBOL programs to DB2 version 8 David Churn DST Systems, Inc. dcchurn@dstsystems.com 56 56

×