DB2: Embedded SQL for C and C++
C & C++ Application Programs

This will walk you through "compiling" an embedded SQL C program. The Ramakrishnan text gives examples of writing embedded SQL C and C++ programs, and the text is basically correct for DB2's version of embedded SQL in C (and C++). See the directories

  • ~db2leduc/sqllib/samples/c/
    and
  • ~db2leduc/sqllib/samples/cpp/

for examples and compilation instructions for C and C++, respectively. See below for another embedded SQL C program.

Embedded SQL for C

  1. Connect.

    One needs to first be connected to the database under which the application program (that is, the embedded SQL C program) is intended to run for the sake of the next two steps. So

    % db2 connect to database

  2. Pre-compile.

    One needs to pre-compile the embedded SQL code to replace the embedded SQL with legitimate C calls. This is done by

    % db2 precompile program.sqc bindfile

    It is convention to name one's embedded SQL C program with ".sqc" at the end to indicate that it is an SQL-C program. The command

    % db2 prep program.sqc bindfile

    is identical. The keywords "prep" and "precompile" mean the same for DB2.

    This pre-compilation step will create a program.c file which is pure C code. It has in it function calls that replace the embedded SQL and will be linked via libraries in the linkage step below.

    This step also creates a program.bnd file, which is used in the bind step discussed next.

  3. Binding.

    The bind step creates a package in DB2. An application program (APP) must have a package counterpart within DB2 to function. The package defines in essence a profile of the APP for the database. In "binding" the package, one can define many aspects of how the APP should be run (for instance, isolation levels), and permissions are checked and verified by DB2 at this stage. Whenever the APP is run later, it will be run with respect to the database as the DB2 user who owns the package to which it is bound.

    To bind the APP (and hence, to create a package) say

    % db2 bind program.bnd

    Various options can be trailed on the command above. These effect the package created, which in turn effects how the APP is run with respect to the database. Read the documentation on "bind" if you are curious.

    The package created will have the same name as program. Packages are like tables in a DB2 database. They are objects which belong to schemas. To see one's current packages, type

    % db2 list packages

    To drop a package, say

    % db2 drop package

    Of course, the associated APP will no longer work. One would have to bind it again before it will work again. Also note that there is no "create package ...". Packages are created via "bind".

  4. Compile.

    Finally, we are at the stage to compile the APP program itself.

    % gcc -I$DB2PATH/include -c program.c

    When "~db2leduc/sqllib/prime" was sourced, it set the environment variable DB2PATH. All the libraries, includes, and such needed for the compile and linking are located in the directory it indicates.

    Note: Just because the DB2 pre-compiler and the bind may have not reported errors, it does not mean that the C compiler will not report errors to you here! This is the first time your program has been parsed and compiled by the C compiler, and will be the first time you get a report of any C-code problems.

  5. Linking.

    In the final step, one must link with the appropriate libraries to create the executable APP.

    % gcc -o program program.o -L$DB2PATH/lib -ldb2

(Okay, so steps four and five could be combined.) If all went well, you now have a working executable APP called program.

Embedded SQL for C++

This is basically the same as for C as described above. Just replace the compiler "gcc" with "g++" for C++.

The convention for naming the DB2 folks use for embedded SQL C++ programs is to add the suffix ".sqC" to the program code file. And they use the suffix ".C" for C++ programs.

Examples of embedded SQL C programs

Here is an example embedded SQL C program. It does not do much, but is instructive. Try pre-compiling / compiling it. Connect to database c341f02 for this. The APP queries a table sailor in schema one. User one has granted select privileges to all on table sailor, so the bind step will be legal.

Note: To download an example, follow the link to the raw text of the program and save that page. The title is a link to the raw text. Do not cut-and-paste the code from this page! Lines can get broken (that is, extra line-feeds inserted) during a cut-and-paste, and these can break the code.

sage.sqc
/*--------------------------------------------------------------------
EXAMPLE of an embedded SQL C Program for DB2.

Connect to database c3421m for this.

This APP takes one argument on the command line, a sailor's SID.  It
then finds the sailor SID's age out of the table ONE.SAILOR (in
database c3421m) and reports it.  A dumb and not very interesting
APP, but it shows how things are done.

P. Godfrey NOV 2002
--------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlenv.h>
#include <sqlcodes.h>
#include <sys/time.h>

#define EXIT   0
#define NOEXIT 1

/*--------------------------------------------------------------------
Include DB2's SQL error reporting facility.
--------------------------------------------------------------------*/

EXEC SQL INCLUDE SQLCA ;

/*--------------------------------------------------------------------
Declare the SQL interface variables.
--------------------------------------------------------------------*/

EXEC SQL BEGIN DECLARE SECTION ;
    short  sage;
    short  sid;
    char   sname[16];
EXEC SQL END DECLARE SECTION ;

/*--------------------------------------------------------------------
Declare variables to be used in the following C program.
--------------------------------------------------------------------*/

char msg[1025];
int rc;
int errcount;

/*--------------------------------------------------------------------
This macro prints the message in the SQLCA if the return code is 0
and the SQLCODE is not 0.
--------------------------------------------------------------------*/

#define PRINT_MESSAGE()                                              \
  {                                                                  \
      if (rc == 0 && sqlca.sqlcode != 0)                             \
      {                                                              \
        sqlaintp(msg, 1024, 0, &sqlca);                              \
        printf("%s\n",msg);                                          \
      }                                                              \
  }

/*--------------------------------------------------------------------
This macro prints out all feilds in the SQLCA.
--------------------------------------------------------------------*/

#define DUMP_SQLCA()                                                 \
  {                                                                  \
    printf("**********  DUMP OF SQLCA  **********************\n");   \
    printf("SQLCAID: %s\n", sqlca.sqlcaid);                          \
    printf("SQLCABC: %d\n", sqlca.sqlcabc);                          \
    printf("SQLCODE: %d\n", sqlca.sqlcode);                          \
    printf("SQLERRML: %d\n", sqlca.sqlerrml);                        \
    printf("SQLERRD[0]: %d\n", sqlca.sqlerrd[0]);                    \
    printf("SQLERRD[1]: %d\n", sqlca.sqlerrd[1]);                    \
    printf("SQLERRD[2]: %d\n", sqlca.sqlerrd[2]);                    \
    printf("SQLERRD[3]: %d\n", sqlca.sqlerrd[3]);                    \
    printf("SQLERRD[4]: %d\n", sqlca.sqlerrd[4]);                    \
    printf("SQLERRD[5]: %d\n", sqlca.sqlerrd[5]);                    \
    printf("SQLWARN: %s\n", sqlca.sqlwarn);                          \
    printf("SQLSTATE: %s\n", sqlca.sqlstate);                        \
    printf("**********  END OF SQLCA DUMP  *******************\n");  \
  }

/*--------------------------------------------------------------------
This macro prints the message in the SQLCA if one exists.  If the
return code is not 0 or the SQLCODE is not expected, an error occurred
and must be recorded.
--------------------------------------------------------------------*/

#define CHECK_SQL(code,text_string,eExit)                            \
  {                                                                  \
    PRINT_MESSAGE();                                                 \
    if (rc != 0 || sqlca.sqlcode != code) {                          \
      printf("%s\n",text_string);                                    \
      printf("Expected code = %d\n",code);                           \
      if (rc == 0) {                                                 \
          DUMP_SQLCA();                                              \
      }                                                              \
      else printf("RC: %d\n",rc);                                    \
      errcount += 1;                                                 \
      if (eExit == EXIT) goto errorexit;                             \
    }                                                                \
  }

/*--------------------------------------------------------------------
The PROGRAM.
--------------------------------------------------------------------*/

main (int argc, char *argv[])
{
    /* Grab the first command argument.  This is the SID. */
    if (argc > 1) {
        sid = atoi(argv[1]);
        printf("SID requested is %d.\n", sid);
    /* If there is no arguement, bail. */
    } else {
        printf("Which SID?\n");
        exit(0);
    }

    EXEC SQL CONNECT TO C3421M;
    CHECK_SQL(0, "Connect failed", EXIT);

    /* Find the name and age of sailor SID. */
    EXEC SQL SELECT SNAME, AGE into :sname, :sage
        FROM ONE.SAILOR
        WHERE sid = :sid;

    CHECK_SQL(0, "The SELECT query failed.", EXIT);

    /* Report the age. */
    printf("Sailor %s's age is %d.\n", sname, sage);

    printf("Executed Successfuly\n") ;
    printf("Bye\n") ;

errorexit:
    EXEC SQL CONNECT RESET;
}

The instance of the table sailor at the time of writing is

SNAME           SID         RATING AGE   
--------------- ----------- ------ ------
yuppy                    22      1     20
lubber                   31      1     25
guppy                    44      2     31
rusty                    58      3     47

So once you have a clean compile, if you ask for example

% sage 44

you should get the response

SID requested is 44.
Sailor guppy's age is 31.
Executed Successfuly
Bye

Note that the SQL statement in the program after the EXEC SQL did not have to be a SELECT query. It could have been any SQL, such as a UPDATE statement.

Do not forget to check out some of the other sample programs found in

  • ~db2leduc/sqllib/samples/c/
    and
  • ~db2leduc/sqllib/samples/cpp/

if you want more examples.

The next example SQC program demonstrates how to open a cursor to walk through the results of a query.

fetcher.sqc
/*--------------------------------------------------------------------
EXAMPLE of an embedded SQL C Program for DB2.

Connect to database c3421m for this.

This APP fetches and prints each of the tuples from ONE.SAILOR (in
database c3421m).

P. Godfrey NOV 2002
--------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlenv.h>
#include <sqlcodes.h>
#include <sys/time.h>

#define EXIT   0
#define NOEXIT 1

/*--------------------------------------------------------------------
Include DB2's SQL error reporting facility.
--------------------------------------------------------------------*/

EXEC SQL INCLUDE SQLCA ;

/*--------------------------------------------------------------------
Declare the SQL interface variables.
--------------------------------------------------------------------*/

EXEC SQL BEGIN DECLARE SECTION ;
    short  sid;
    short  sage;
    short  rating;
    char   sname[16];
EXEC SQL END DECLARE SECTION ;

/*--------------------------------------------------------------------
Declare variables to be used in the following C program.
--------------------------------------------------------------------*/

char msg[1025];
int rc;
int errcount;

/*--------------------------------------------------------------------
This macro prints the message in the SQLCA if the return code is 0
and the SQLCODE is not 0.
--------------------------------------------------------------------*/

#define PRINT_MESSAGE()                                              \
  {                                                                  \
      if (rc == 0 && sqlca.sqlcode != 0)                             \
      {                                                              \
        sqlaintp(msg, 1024, 0, &sqlca);                              \
        printf("%s\n",msg);                                          \
      }                                                              \
  }

/*--------------------------------------------------------------------
This macro prints out all feilds in the SQLCA.
--------------------------------------------------------------------*/

#define DUMP_SQLCA()                                                 \
  {                                                                  \
    printf("**********  DUMP OF SQLCA  **********************\n");   \
    printf("SQLCAID: %s\n", sqlca.sqlcaid);                          \
    printf("SQLCABC: %d\n", sqlca.sqlcabc);                          \
    printf("SQLCODE: %d\n", sqlca.sqlcode);                          \
    printf("SQLERRML: %d\n", sqlca.sqlerrml);                        \
    printf("SQLERRMC: %s\n", sqlca.sqlerrmc);                        \
    printf("SQLERRP: %s\n", sqlca.sqlerrp);                          \
    printf("SQLERRD[0]: %d\n", sqlca.sqlerrd[0]);                    \
    printf("SQLERRD[1]: %d\n", sqlca.sqlerrd[1]);                    \
    printf("SQLERRD[2]: %d\n", sqlca.sqlerrd[2]);                    \
    printf("SQLERRD[3]: %d\n", sqlca.sqlerrd[3]);                    \
    printf("SQLERRD[4]: %d\n", sqlca.sqlerrd[4]);                    \
    printf("SQLERRD[5]: %d\n", sqlca.sqlerrd[5]);                    \
    printf("SQLWARN: %s\n", sqlca.sqlwarn);                          \
    printf("SQLSTATE: %s\n", sqlca.sqlstate);                        \
    printf("**********  END OF SQLCA DUMP  *******************\n");  \
  }

/*--------------------------------------------------------------------
This macro prints the message in the SQLCA if one exists.  If the
return code is not 0 or the SQLCODE is not expected, an error occurred
and must be recorded.
--------------------------------------------------------------------*/

#define CHECK_SQL(code,text_string,eExit)                            \
  {                                                                  \
    PRINT_MESSAGE();                                                 \
    if (rc != 0 || sqlca.sqlcode != code) {                          \
      printf("%s\n",text_string);                                    \
      printf("Expected code = %d\n",code);                           \
      if (rc == 0) {                                                 \
          DUMP_SQLCA();                                              \
      }                                                              \
      else printf("RC: %d\n",rc);                                    \
      errcount += 1;                                                 \
      if (eExit == EXIT) goto errorexit;                             \
    }                                                                \
  }

/*--------------------------------------------------------------------
The PROGRAM.
--------------------------------------------------------------------*/

main (int argc, char *argv[]) {
    EXEC SQL CONNECT TO C3421M;
    CHECK_SQL(0, "Connect failed", EXIT);

    /* Find the name and age of sailor SID. */
    EXEC SQL DECLARE sailorC CURSOR FOR
        SELECT SID, SNAME, AGE RATING
            FROM ONE.SAILOR;

    CHECK_SQL(0, "The SELECT query failed.", EXIT);

    EXEC SQL OPEN sailorC;

    printf("sid sname           age rating\n");
    while (1) {
        EXEC SQL FETCH sailorC INTO :sid, :sname, :sage, :rating;
        if (SQLCODE != 0) break;

        printf("%3d %-15s %3d    %3d\n", sid, sname, sage, rating);
    }

    EXEC SQL CLOSE sailorC;

errorexit:
    EXEC SQL CONNECT RESET;
}