1. An introduction to Embedded
SQL for NonStop SQL/MX
Frans Jongma,
Hewlett Packard Enterprise
Advanced Technology Center
NonStop Enterprise Division
Version 1.0
Date: October 11, 2019
Contents
Introduction................................................................................................................................ 2
Audience ................................................................................................................................ 2
Assumptions........................................................................................................................... 2
Best practice........................................................................................................................... 3
From source to executable......................................................................................................... 3
Preprocessing and compilation............................................................................................... 3
Example 1, simple...................................................................................................................... 3
Downside of simple example.................................................................................................. 4
Example 2, managed module location ....................................................................................... 4
Controlling the module names................................................................................................ 5
Controlling schema names ..................................................................................................... 6
Example 3, schema flexibility ..................................................................................................... 6
Example 4, combined module control and schema flexibility...................................................... 8
Examine execution plans ........................................................................................................... 9
Summary ..................................................................................................................................10
References............................................................................................................................10
Appendix...................................................................................................................................11
COBOL Compilation process flow .........................................................................................11
C C++ Compilation process flow............................................................................................12
Simple example verbose output.............................................................................................13
Example 1 COBOL source code............................................................................................14
2. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -2-
Introduction
3GL languages such as COBOL and C have a specific SQL syntax that is translated by a
preprocessor into native calls to the database before the language and SQL compilers execute
and produce an executable program. This method is referred to as embedded SQL or static
SQL and differs from the more dynamic ways that is used in ODBC or JDBC programs, where
the statements are compiled as needed when the program executes. The SQL execution plans
that are created by a post-compilation step (the SQL compile) are stored by SQL/MX in so-
called module files separated from the executable program.
There are many options in creating and managing programs and module files, all of them are
listed in the SQL/MX Programming Manual for C and COBOL. However, for a first time user,
this amount of information may be overwhelming and confusing. This document will provide an
introduction to give users a fast start.
Audience
The paper is written for users who are new to NonStop SQL/MX and need to develop programs
in C or COBOL. The audience includes NonStop users that are familiar with NonStop SQL/MP
and how SQL/MP supports embedded SQL.
Assumptions
I assume the natural environment for NonStop SQL/MX, operation in the OSS operating
environment. While SQL/MX supports the Guardian environment, for ease of use and
understanding, it is not my recommended environment.
The examples show examples in COBOL, however since the method to compile is the same
between COBOL and C, C/C++ developers will find it useful too. The difference in compilers is
listed in the table below. The process flows are listed in the sections COBOL Compilation
process flow and C C++ Compilation process flow in the Appendix.
COBOL C/C++
SQL/MX Host language
precompiler
mxsqlco mxsqlc
Host language compiler xcobol or ecobol for J-series
software releases
c89
SQL/MX SQL Compiler mxCompileUserModule mxCompileUserModule
3. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -3-
Best practice
Naming tables and views in the source programs may best be done without qualifying them to a
dedicated catalog and schema. It is a better option to set the catalog and schema at a central
place in the source program with a DECLARE CATALOG or DECLARE SCHEMA statement. It
is also possible to define the catalog or schema as compiler options for the ultimate flexibility.
From source to executable
Host language source code uses SQL with a specific syntax called embedded SQL. These
statements are identified by the begin and end tags EXEC SQL and END-EXEC.
Some examples of embedded SQL are shown below. They show definition of variables used by
the program in the DECLARE section of the programs and an example of a SQL DML
statement.
EXEC SQL BEGIN DECLARE SECTION.
EXEC SQL INVOKE PARTS END-EXEC.
EXEC SQL END DECLARE SECTION.
EXEC SQL SELECT * FROM PARTS WHERE …… END-EXEC.
The statements between these tags, are processed by a SQL/MX preprocessor and translated
into host language (COBOL or C) statements, and these will be translated into machine code by
the standard COBOL and C compilers.
Preprocessing and compilation
The SQL/MX preprocessor takes a source input file, and produces a language source file that is
in turn the input for the language processor which produces an object file. This object can be a
load module or an executable object, depending on the type of program.
The SQL statements are processed by the SQL compiler, which uses the database metadata
and table statistics to produce an execution plan. This execution plan is stored in a module file
on disk. The executable program includes references to this module file (generated by the
preprocessor), such that when a program is executed, the corresponding modules can be
loaded to obtain and execute the execution plan.
Example 1, simple
The simplest way to compile a program is by invoking the language compiler which uses
definitions in the program and some defaults to produce the executable and the module file.
4. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -4-
Let’s look at the following example, which compiles a COBOL source code1
sampl.ecob into
an executable called sampl. The xcobol compiler will invoke the necessary compiler programs,
based on the execution options
xcobol –Wsqlmx –Wmxcmp sampl.ecob –o sampl -Wverbose
The –Wsqlmx option tells the compiler that the program contains SQL/MX embedded SQL,
and so it will launch the SQ/MX COBOL preprocessor mxsqlco.
The –Wmxcmp option tells the compiler that the generated object (sampl) needs to be
processed by the SQL/MX compilers mxCompileUserModule and mxcmp.
The –Wverbose option causes the individual steps to be listed. It shows all the steps of the
compilation process and is listed in the appendix Simple example verbose output.
With this simple command, the generated modules will be stored in the default module directory,
/usr/tandem/sqlmx/USERMODULES. While it is nice to have a default place for all the
modules, the downside of the simple compilation is a single directory filled with many modules.
Downside of simple example
The SQL compiler will generate unique module files unless instructed by either compiler options
or an embedded SQL statement that defines the name of the module. An example of a default
module name is FRANS.PERF.SQLMX_DEFAULT_MODULE_259723530653478123. The
SQL preprocessor includes a catalog and schema name (in this case, FRANS.PERF) in the
name of the generated module. A subsequent compilation of the program will create a new
module, which means that the default USERMODULES directory will contain many modules
very quickly. There are ways to get a better control over the name of the module and the
location it is stored in as is shown in the next examples.
Example 2, managed module location
The simple one-step example will create all modules in the same location. A better option is to
co-locate the modules with the executables or to place them in separate directories. This can be
done by executing the SQL compile step as a separate one after the language compilation.
Such a 2-step compilation is shown below. Note, the –Wverbose option omitted in the
following examples.
xcobol -Wsqlmx sampl.ecob -o sampl
mxCompileUserModule -g moduleLocal sampl
1 The source code is listed in the appendix of this paper.
5. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -5-
The mxCompileUserModule program invokes the SQL/MX compiler and will now create a
module in the local directory due to the –g moduleLocal option. It is even possible to
specify a specific directory to place the modules. That is useful, however, it requires that this
directory needs to be defined in an environment variable when the program is executed or else
the module will not be found. The environment variable, called _MX_MODULE_SEARCH_PATH,
is used as a search path and needs to contain the names of the directories to search for
modules, similar to the PATH and CLASSPATH variables. This paper will use discuss co-
located modules, where program and module are placed in the same directory.
Controlling the module names
Automatically generated module names are easy for a developer, but it will burden a system
administrator with the task of removing stale modules2
. It may therefore be better to explicitly
name the modules and let SQL/MX add the catalog and schema names to the name, since it is
useful to know to which schema a module belongs.
With the simple 2-step example, the module name can be defined with a DECLARE MODULE
statement in the program source. The example also uses DECLARE statements to define the
catalog and schema that the program will use.
The name of the module is defined along with the other data fields, while the catalog and
schema are defined later in the PROCEDURE DIVISION of the program.
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
* The MODULE statement will cause a module created
* named <cat>.<sch>.SAMPL in the module directory
EXEC SQL MODULE "SAMPL" END-EXEC.
….. data definitions
…..
PROCEDURE DIVISION.
…..
EXEC SQL DECLARE CATALOG 'frans' END-EXEC.
EXEC SQL DECLARE SCHEMA 'perf' END-EXEC.
When this code is compiled, a module called FRANS.PERF.SAMPL is created, either in the
default (global) directory, or in the local directory if the moduleLocal option is used. When
2 Note: The mxci command DISPLAY USE OF SOURCE [‘module name’] will show the source file
belonging to this module. In case of stale modules, multiple modules will be referring to the same source
file. See the SQL/MX Reference Manual for information about the DISPLAY USE OF …. Command.
6. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -6-
the program is subsequently recompiled, this module will be replaced and no stale modules will
exist, unless the program is removed without removing the corresponding module.
Controlling schema names
The SQL/MX precompiler creates the name of the module, which includes the catalog and
schema name. The DECLARE MODULE statement contains only the part of the name without
catalog and schema. The desired catalog and schema name to name the module can be
passed to the language compiler with the –WmoduleSchema=<cat.schema> option.
xcobol -Wsqlmx -WmoduleSchema=frans.perf sampl.ecob -o sampl
mxCompileUserModule -g moduleLocal sampl
Catalog and schema are SQL identifiers and are used in uppercase by SQL/MX3
. After these
two steps, a module with the name FRANS.PERF.SAMPLE is created in the current directory
along with the sampl executable.
Example 3, schema flexibility
To further improve, the source program can be made independent of the schema4
that is used.
The next example shows how to compile the program with the possibility to create modules in a
different schema (for example when moving from development to test to production) without
having to recompile from scratch. This allows the compiled program to be moved from one
system to another, only SQL-compiling the module to the target database environment.
In the previous examples, we let the source program define the schema with a DECLARE
SCHEMA statement. To provide schema flexibility, omit the DECLARE CATALOG and
DECLARE SCHEMA statements. This however means that the precompiler must be executed
as a separate step, because it needs another parameter that the language compiler does not
pass. This parameter is invokeSchema, which is used when EXEC SQL INVOKE is used to
import the column definitions from the database, which is used to make sure that a program
uses the correct column definitions.
The program sampl3 uses the INVOKE statement to obtain the column definitions of the PARTS
table, but does not declare the schema.
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
EXEC SQL MODULE "SAMPL" END-EXEC.
3 It is possible to use mixed case and special characters in SQL/MX, by enclosing them in double quotes.
I consider it bad practice and will not discuss it here.
4 For readability, I use the term schema as the combination of catalog and schema.
7. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -7-
* Get the record layout of PARTS
EXEC SQL INVOKE PARTS END-EXEC.
….. data definitions
…..
PROCEDURE DIVISION.
…..
* In reality, these lines are not present in the source.
* EXEC SQL DECLARE CATALOG 'frans' END-EXEC.
* EXEC SQL DECLARE SCHEMA 'perf' END-EXEC.
…..
To compile the program we use three steps, the preprocessor, the language processor and the
SQL compiler. The precompiler for COBOL, mxsqlco, uses value of moduleSchema to
create the name of the module and the –Q invokeSchema value to retrieve the record
definition of the PARTS table. And produces the generated COBOL source in sampl3.cbl. This
is input to the language compiler.
mxsqlco -g moduleSchema=frans.perf -Q invokeSchema=frans.perf
sampl3.ecob
xcobol -Wsqlmx -o sampl3 sampl3.cbl
mxCompileUserModule -g moduleLocal –d schema=frans.perf sampl3
The final step, mxCompileUserModule, creates the modules locally (this means they are
not created I the SQL/MX USERMODULES directory), and uses the schema name to get the
information it needs to compile an execution plan.
The next sequence of events show how the program can be targeted to use a new schema. In
this example, a row will be inserted in the PERF.PARTS table, but it will fail on a duplicate key
exception. The program shows the full name of the table, which includes the schema it
accesses. Then the only the module is recompiled to use the HR schema and the program
outpur shows that the same business code in sampl3 will access the HR.PARTS table.
~/compile> ./sampl3
This example uses a static cursor.
Enter lowest part number to be retrieved:
11
sqlerrors: 23000, -000008102
Table : FRANS.PERF.PARTS
Column :
SQLSTATE: 23000
Message : *** ERROR[8102] The operation is prevented by a
primary key PARTS_564349585_9263 on table FRANS.PERF.PARTS.
8. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -8-
Create a module to use the frans.HR schema.
~/compile> mxCompileUserModule -g moduleLocal -d schema=frans.HR
sampl3
Run the same executable
~/compile> ./sampl3
This example uses a static cursor.
Enter lowest part number to be retrieved:
11
sqlerrors: 23000, -000008102
Table : FRANS.HR.PARTS
Column :
SQLSTATE: 23000
Message : *** ERROR[8102] The operation is prevented by a
primary key PARTS_118992335_3782 on table FRANS.HR.PARTS.
~/compile>
This example shows the method to move binary programs from one system to another and only
the module files need to be recompiled on the target database.
Note however, that this example uses a module called FRANS.PERF.SAMPL even though it
can access the PARTS table in schema PERF or HR. The first two parts of the module name
represent a catalog and schema, however, this is only a convention. The next example shows
how to control the complete module name.
Example 4, combined module control and schema flexibility
In this example, modules have names that do not include a catalog or schema, since the
application business code can run in different environments (for example development, test,
integration and production). Instead, in this example, the catalog and schema parts of the
module name are used for application name and version5
.
Important note: Do not use special characters (especially period) in the module name. While
the program may execute fine with such a module, the mxci DISPLAY USE OF commands
expect a three part name, with a “.” as separation character.
5 Including the version number in a module is used as an example of how one might organize modules.
Lifecycle version information might also be kept in source control systems such as git.
9. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -9-
The module directive in the source file (sampl4.ecob) is specified as follows:
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
* The MODULE statement will cause a module created named
* MYAPP.V_0_1.SAMPL4 in the module directory
EXEC SQL MODULE "MYAPP"."V_0_1"."SAMPL4" END-EXEC.
To compile the program in three steps:
# Use 2 environment variables to keep things simple:
export P=sampl4
export SCHEMA=FRANS.PERF
# run the three steps
mxsqlco -Q invokeSchema=$SCHEMA $P.ecob
xcobol -Wsqlmx -o $P $P.cbl
mxCompileUserModule -g moduleLocal -d SCHEMA=$SCHEMA $P
SQL compile the module for use on a different schema, use:
mxCompileUserModule -g moduleLocal -d SCHEMA=frans.hr sampl4
Examine execution plans
An advantage of having meaningful names for modules is that they now can be used easily to
examine the generated SQL execution plans. The following EXPLAIN statement shows the
formatted execution plans used by program sampl3.
~/compile> mxci
Hewlett Packard Enterprise NonStop(TM) SQL/MX Conversational Interface 3.6.1
(c) Copyright 2003-2018 Hewlett Packard Enterprise Development LP.
>>EXPLAIN options 'f' '%' from '/home/hp/frans/compile/FRANS.PERF.SAMPL3' ;
Statement: GET_BY_PARTNUM
LC RC OP OPERATOR OPT DESCRIPTION CARD
---- ---- ---- -------------------- -------- -------------------- ---------
2 . 3 root 3.29E+001
1 . 2 partition_access 3.29E+001
. . 1 file_scan fr PARTS (s) 3.29E+001
…. ….
(Other statements omitted)
10. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -10-
Summary
Using a few simple examples we have seen how SQL/MX translates embedded SQL statement
into an executable program and a SQL module file. The examples have been kept very simple,
and do not discuss adding multiple object files that are linked together into an executable
program. The Programming Manual for C and COBOL has the details. This paper will help you
finding the right options for building larger programs.
The module file names can be defined by the user, which has system management advantages.
Using the default location and the default naming scheme will result in a large amount of, often
unused, modules in the /usr/tandem/sqlmx/USERMODULES directory. Decoupling the
program source code from the actually used catalog and schema allow an easy move of objects
between execution environments. In cases where application run on systems with differently
named catalogs or schemas, it is good practice to define module names based on a convention
that is not based on catalog and schema, but on something else, such as application name and
possibly version or subclass of the application.
References
The following manuals can be used to get more detailed information. They are accessible via
the HPE Support Center, for L-series software go to https://hpe.com/info/nonstop-ldocs, and for
J-series software use https://hpe.com/info/nonstop-jdocs.
Some manuals have the release number in the title and not shown in the titles below.
SQL/MX Programming Manual for C and COBOL.
SQL/MX Reference manual.
SQL/MP to SQL/MX Database and Application Migration Guide.
11. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -11-
Appendix
COBOL Compilation process flow
The following diagram shows the compilation steps. This figure was taken from the SQL/MX
Programming C and COBOL manual
12. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -12-
C C++ Compilation process flow
The following diagram shows the compilation steps. This figure was taken from the SQL/MX
Programming C and COBOL manual
14. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -14-
/tmp/AAAqaabWa197661ACICCH
(/usr/tandem/sqlmx/USERMODULES/FRANS.PERF.SQLMX_DEFAULT_MODULE_2597235
31183946022)
0 errors, 0 warnings, 0 statements affected; 17 statements total
1 modules found, 1 modules extracted.
1 mxcmp invocations: 1 succeeded, 0 failed.
xcobol: /usr/tandem/sqlmx/bin/mxCompileUserModule exited, returning 0.
xcobol: Exiting with status 0; 0 error(s).
~/compile>
Example 1 COBOL source code
This sample program is a slightly changed copy of the example from the SQL/MX 3.6
Programming Manual for C and COBOL. The change is the addition of the INSERT statement
right before the cursor is opened. Note that duplicate keys will cause an error, this error is used
to show that the examples can run the same code on different schemas.
* ---------------------------------------------------------------
* compile this program simply in OSS with:
* [x|e]cobol -Wsqlmx -Wmxcmp sampl.ecob -o sampl –Wverbose
*
* Description: Using a Static SQL Cursor
* Statements: Static DECLARE CURSOR
* BEGIN WORK
* OPEN
* FETCH
* Positioned UPDATE
* CLOSE
* COMMIT WORK
* WHENEVER
* GET DIAGNOSTICS
*---------------------------------------------------------------
* Table definition
* CREATE TABLE PARTS
* (
* PARTNUM NUMERIC(4, 0) UNSIGNED NO DEFAULT HEADING
* 'Part/Num' NOT NULL
* , PARTDESC CHAR(18) CHARACTER SET ISO88591 NO
* DEFAULT HEADING 'Part Description' NOT NULL
* , PRICE NUMERIC(8, 2) NO DEFAULT HEADING 'Price'
* NOT NULL
* , QTY_AVAILABLE NUMERIC(5, 0) DEFAULT 0 HEADING
* 'Qty/Avail' NOT NULL
* , ORDER_DATE DATE DEFAULT CURRENT_DATE
* , PRIMARY KEY (PARTNUM ASC)
* )
* ;
* --- SQL operation complete.
*
15. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -15-
IDENTIFICATION DIVISION.
PROGRAM-ID. Program-exF62.
DATA DIVISION.
WORKING-STORAGE SECTION.
* program uses the INVOKE HVs to insert the row
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
* The MODULE statement will cause a module created named
* MYAPP.V_0_1.SAMPL4 in the module directory
* Note that the three part name must follows the rules
* for SQL/MX Catalog,schema, and object, separated by a "."
EXEC SQL MODULE "MYAPP"."V_0_1"."SAMPL4" END-EXEC.
* GET THE CORRECT RECORD LAYOUT
* if the table name is not qualified with cat and schema,
* the preprocessor must be called
* with -Q invokeSchema=cat.sch
*
EXEC SQL INVOKE PARTS END-EXEC.
01 sqlstate pic x(5).
01 sqlcode pic s9(9) comp.
01 hv-partnum pic 9(4) comp.
01 hv-partdesc pic x(18).
01 hv-price pic s9(6)v9(2) comp.
01 hv-qty-available pic s9(7) comp.
* in SQL/MP the date column is declared as PIC X(10) ,
* and the insert uses the TYPE AS DATE clause when inserting a row
* SQL/MX however supports (and needs) the column defined as DATE,
* the INSERT statment does not require the non-ANSI TYPE AS construct.
01 hv-order-date DATE value "2019-09-12".
* hv-order-date for SQLMP definition
*01 hv-order-date pic x(10) value "2019-09-12".
01 hv-num pic s9(9) comp.
01 hv-sqlstate pic x(5).
01 hv-tabname pic x(128).
01 hv-colname pic x(128).
01 hv-msgtxt pic x(128).
01 in-partnum pic 9(4) comp.
01 i pic s9(9) comp.
EXEC SQL END DECLARE SECTION END-EXEC.
01 sqlstate-ok pic x(5) value "00000".
01 sqlstate-nodata pic x(5) value "02000".
01 sqlstate-save pic x(5).
01 sqlcode-save pic s9(9) comp.
PROCEDURE DIVISION.
START-LABEL.
DISPLAY "This example uses a fully qualified module name, but catalog and schema
names are independent".
EXEC SQL WHENEVER SQLERROR GOTO sqlerrors END-EXEC.
16. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -16-
* Declare static cursor.
EXEC SQL DECLARE get_by_partnum CURSOR FOR
SELECT partnum, partdesc, price, qty_available
FROM parts
WHERE partnum >= :in-partnum
FOR UPDATE OF partdesc, price, qty_available
END-EXEC.
* Read in-partnum from terminal.
DISPLAY "Enter lowest part number to be retrieved: ".
ACCEPT in-partnum.
* Begin the transaction.
move in-partnum to partnum
move "New part" to partdesc
move 120 to price
move 528 to qty-available
move "2019-09-13" to order-date.
EXEC SQL BEGIN WORK END-EXEC.
EXEC SQL INSERT INTO PARTS (
PARTNUM,
PARTDESC,
PRICE,
QTY_AVAILABLE,
ORDER_DATE ) VALUES
(
:partnum,
:partdesc,
:price,
:qty-available,
:order-date
)
END-EXEC.
* Open the cursor.
EXEC SQL OPEN get_by_partnum END-EXEC.
* Fetch the first row of the result from table.
EXEC SQL FETCH get_by_partnum
INTO :hv-partnum, :hv-partdesc,
:hv-price, :hv-qty-available
END-EXEC.
* Update qty_available if qty_available is less than 1000.
PERFORM UNTIL sqlstate = sqlstate-nodata
IF hv-qty-available < 1000
EXEC SQL UPDATE parts
SET qty_available = qty_available + 100
WHERE CURRENT OF get_by_partnum
END-EXEC.
DISPLAY "Update of part number: " hv-partnum
END-IF
EXEC SQL FETCH get_by_partnum
INTO :hv-partnum, :hv-partdesc,
:hv-price, :hv-qty-available
END-EXEC.
END-PERFORM.
* Close the cursor.
EXEC SQL CLOSE get_by_partnum END-EXEC.
17. NonStop Advanced Technology Center
An introduction to Embedded SQL for NonStop SQL/MX -17-
* Commit any changes.
EXEC SQL COMMIT WORK END-EXEC.
IF sqlstate = sqlstate-ok
DISPLAY "The program completed successfully.".
STOP RUN.
****************************************************************
sqlerrors SECTION.
****************************************************************
move sqlstate to sqlstate-save.
move sqlcode to sqlcode-save.
display "sqlerrors: " sqlstate ", " sqlcode.
EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.
IF sqlstate not = sqlstate-ok
EXEC SQL GET DIAGNOSTICS
:hv-num = NUMBER
END-EXEC.
PERFORM VARYING i FROM 1 BY 1 UNTIL i > hv-num
MOVE SPACES TO hv-msgtxt
EXEC SQL GET DIAGNOSTICS EXCEPTION :i
:hv-tabname = TABLE_NAME,
:hv-colname = COLUMN_NAME,
:hv-sqlstate = RETURNED_SQLSTATE,
:hv-msgtxt = MESSAGE_TEXT
END-EXEC.
DISPLAY "Table : " hv-tabname
DISPLAY "Column : " hv-colname
DISPLAY "SQLSTATE: " hv-sqlstate
DISPLAY "Message : " hv-msgtxt
END-PERFORM
END-IF.
move sqlstate-save to sqlstate.
move sqlcode-save to sqlcode.
* STOP RUN.
****************************************************************
END PROGRAM Program-exF62.
****************************************************************