Using SQL in application programs

 

Limits of SQL

Interactive SQL suits for

SQL is There are more user friendly database interfaces for making ad hoc queries and for producing simple reports. These interfaces usually implement the ideas put forward in Query-By-Example. Usually, end users, however, use databases through application programs. These provide the users with

SQL in application programs

Application programs are programmed in some programming language. One problem in programming database applications is how to embed the database operations into the programs. Common general purpose programming languages (C, Cobol, Pascal, etc.) do not include databases in their kernel structures. The alternatives in programming database applications are either to use special database programming languages or to use add-ons for general purpose programming languages.

Two add-on techniques are commonly used

Query processing, in general, takes place as depicted in the following picture. A query is first specified. Then it is compiled and executed. After execution the answer of the query is processed within a program loop.

 

 

 

Embedded SQL

In embedded SQL, SQL-statements can be used mixed with the statements of the used programming language, for example C or Cobol. In order to distinguish the SQL-statements from the statements of the host programming language these statements are marked as belonging to the SQL (EXEC SQL - marks). A pre-compiler is needed to analyze the embedded SQL-statements and to transform them into calls of functions defined in a database interface library. These functions will execute the actual database operations. The output of the pre-compiler is then compiled using the standard compiler of the used programming language.

 

Database interface libraries are specific to database management systems as well as the pre-compilers. However, the way of how the database operations are embedded in the programs is standardized. Thus it should be possible to change the database management system and just to recompile the program to work with a new dbms. The standard specifies, for example:

An example in C:

/* include the header files */ 
	 #include <stdio.h> 
	 #include <string.h> 
/* include definitions of SQL communication Area */ 
	 #include <sqlca.h> 
   #define ID_len 20 
	 
/* define the variables to provide data for SQL*/ 
/* EXEC SQL marks statements ment for the pre-compiler */ 
	 EXEC SQL BEGIN DECLARE SECTION; 
	    varchar identifier[ID_len], password[ID_len]; 
		varchar searchkey[40]; 
	 EXEC SQL END DECLARE SECTION; 
/* define variables to reveive data from the database */ 
   struct { 
	   varchar name[40]; 
	   varchar lastcontact[20]; 
   } studentrow; 
	 
/* define the indicatorvariables. These control the stutus of
      answer values - real or null, The value is non-zero in case
      of error or exception  */ 
   struct {short name_ind, lastcontact_ind; } student_ind;
   int student_counter=0;
   
/* define some auxiliary functions */ 
   void ask_identifier();
   void ask_searchkey(); 
   void sql_error(); 
	
/* the main program */	
   main() {
      /* Register function sql_error() as the error handler */ 
      EXEC SQL WHENEVER SQLERROR DO sql_error("Oracle error \n");
      /* get the user id and password */ 
      ask_identifier(&identifier,&password);
      /* establish a connection to the database */
      /* A colon in front of variable name indicates that the value of
	     the variable should be used */
      EXEC SQL CONNECT :identifier IDENTIFIED BY :password; 
      
	  /* define the query, the value for variable searchkey is not 
	     evaluated yet
	  */
      EXEC SQL DECLAEE student_query CURSOR FOR
         SELECT rpad(substr(lastname||' '||firstnames,1,40),40) name,
                to_char(date_last_used,'DD.MM.YYYY') 
         FROM STUDENT
         WHERE upper(lastname) LIKE upper(:searckey)
         ORDER BY name;

    /* ask the user to give the search condition */ 
         ask_searchkey(&searchkey);
	  /* execute the query */
    /* the value for variable searchkey is evaluated now */
        EXEC SQL OPEN student_search;
	  /* specify that the control leaves the loop when the are no more
	     records to process  */
       EXEC SQL WHENEVER NOT FOUND DO break;
    /* processing of the answer records */ 
       for (;;) {
          /* activate the next row of the answer */
          EXEC SQL FETCH student_search 
                 INTO :studentrow INDICATOR :student_ind;
          /* print the retrieved record */
          printf(" %s latest contact: %s \n", studentrow.name.arr,
                  studentrow.latestcontact.arr);
          student_counter++;
       } 
       printf("\nNumber of students; %d",student_counter); 
      /* records have been processed, release the resources */
      ECEC SQL CLOSE student_search;
            
	    /* just to be sure */
        EXEC SQL COMMIT WORK RELEASE; 
        exit(0); 
   }
      
   void ask_identifier(varchar *username, varchar *userpasswd) { 
           /* ask the user for user id and password */
           /* code not included here */
   } 
		
   void ask_searchkey(varchar *key) {
           /* ask the user for the mask to be compared with the lastname */
           /* code not included here */
   }
		
   void sql_error(char *msg) {
          /* report on error */ 
         char err_msg[512]; 
         int buff_len, msg_len; 
         EXEC SQL WHENEVER SQLERROR CONTINUE;
         printf("\n%s\n",msg); 
         /* sqlglm() provides the message text */ 
         buff_len = sizeof(err_msg); 
         sqlglm(err_msg,&buff_len, &msg_len); 
         printf("%.*s\n", msg_len,err_msg);
         /* Rollback, if database has been modified */ 
         EXEC SQL ROLLBACK RELEASE; 
         exit(1); 
  }
      

 

A kernel concept in database programming is cursor (the result set). Cursor is

Database operations may fail due to various reasons. The program should always check whether the operation succeeded or failed. In the above program this is done using WHENEVER clauses. This can also be done by examining the variable sqlstate (is non-zero if the operation fails).

 

Application programming interfaces (APIs)

A database application programming interface (database API) is a library of functions to carry out database operations. Each database management system provides a library of its own. For example, Oracle has a library called Oracle Call Level Interface (Oracle CLI). This is actually the library used in the calls generated by the embedded SQL pre-compiler. Database management system specific libraries are called native APIs.

There are also libraries, for example ODBC (Microsoft Open Database Connection) and JDBC (for Java), that are independent of database management systems. These libraries make it possible to use various database management systems, even within one program. On the programmers point of view these libraries provide a common interface for database programming. However, to use a certain type of database, a driver for that particular type is needed. For example, an Oracle driver is needed in order to use Oracle databases. In the following we outline the use of database in Java programming language using JDBC -API.

Introduction to JDBC

 
JDBC is a class library that provides classes and methods for using a database. The kernel classes of the library are
DriverManager

Connection
Statement
ResultSet
PreparedStatement

Database programming language

Architecture of database applications

The early database applications were mainframe applications. All the processing in the application was done in one mainframe computer. Simple terminals without any processing capacity were used for the user interface. Because the terminals did not have processing capacity the screen images had to be constructed in the mainframe computer before they were passed to the terminal. Also all checks for the input values were carried out in the mainframe computer.

Currently many database applications are client-server applications. The database resides in one or more database servers and the user interfaces work on different client computers. Computer networks and data communication techniques are used to connect the clients and the servers. Because both the clients and the server have capacity to process data, the workload can be divided between them. Typically the database server takes care of database operations and the clients take care of the user interface and the validation of input data. Information concerning the user interface need not be passed between the clients and the server, only the queries and their answers.

It is also possible to balance the workload between the clients and the server. The designer has to think what tasks to carry out in the server and what in the clients.

If all the processing is done in the server

If all the processing is distributed to the clients