<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.zcubes.com/index.php?action=history&amp;feed=atom&amp;title=Yurttas%2FPL%2FDBL%2Foracle%2FF%2FR%2For-proc.html</id>
	<title>Yurttas/PL/DBL/oracle/F/R/or-proc.html - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.zcubes.com/index.php?action=history&amp;feed=atom&amp;title=Yurttas%2FPL%2FDBL%2Foracle%2FF%2FR%2For-proc.html"/>
	<link rel="alternate" type="text/html" href="http://wiki.zcubes.com/index.php?title=Yurttas/PL/DBL/oracle/F/R/or-proc.html&amp;action=history"/>
	<updated>2026-04-28T04:36:22Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.2</generator>
	<entry>
		<id>http://wiki.zcubes.com/index.php?title=Yurttas/PL/DBL/oracle/F/R/or-proc.html&amp;diff=82546&amp;oldid=prev</id>
		<title>MassBot1: Created page with &quot;=Introduction to Pro*C - Embedded SQL   ----=    * Overview  * Pro*C Syntax  ** yurttas/...&quot;</title>
		<link rel="alternate" type="text/html" href="http://wiki.zcubes.com/index.php?title=Yurttas/PL/DBL/oracle/F/R/or-proc.html&amp;diff=82546&amp;oldid=prev"/>
		<updated>2013-11-05T05:35:33Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;=Introduction to Pro*C - Embedded SQL   ----=    * &lt;a href=&quot;/index.php?title=Yurttas/PL/DBL/oracle/F/R/&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Yurttas/PL/DBL/oracle/F/R/ (page does not exist)&quot;&gt;Overview&lt;/a&gt;  * &lt;a href=&quot;/index.php?title=Yurttas/PL/DBL/oracle/F/R/&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Yurttas/PL/DBL/oracle/F/R/ (page does not exist)&quot;&gt;Pro*C Syntax&lt;/a&gt;  ** yurttas/...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=Introduction to Pro*C - Embedded SQL   ----=&lt;br /&gt;
&lt;br /&gt;
* [[yurttas/PL/DBL/oracle/F/R/#overview|Overview]]&lt;br /&gt;
* [[yurttas/PL/DBL/oracle/F/R/#pro*c syntax|Pro*C Syntax]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#sql|SQL]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#preprocessor directives|Preprocessor Directives]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#statement labels|Statement Labels]]&lt;br /&gt;
* [[yurttas/PL/DBL/oracle/F/R/#host variables|Host Variables]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#basics|Basics]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#pointers|Pointers]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#structures|Structures]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#arrays|Arrays]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#indicator variables|Indicator Variables]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#datatype equivalencing|Datatype Equivalencing]]&lt;br /&gt;
* [[yurttas/PL/DBL/oracle/F/R/#error handling|Error Handling]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#sqlca|SQLCA]]&lt;br /&gt;
** [[yurttas/PL/DBL/oracle/F/R/#whenever statement|WHENEVER Statement]]&lt;br /&gt;
* [[yurttas/PL/DBL/oracle/F/R/#demo programs|Demo Programs]]&lt;br /&gt;
* [[yurttas/PL/DBL/oracle/F/R/#c++ users|C++ Users]]&lt;br /&gt;
* [[yurttas/PL/DBL/oracle/F/R/#list of embedded sql statements supported by pro*c|List of Embedded SQL Statements Supported by Pro*C]]&lt;br /&gt;
&lt;br /&gt;
===---- &amp;lt;font size=&amp;quot;+1&amp;quot;&amp;gt;Overview&amp;lt;/font&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Embedded SQL is a method of combining the computing power of a high-level language like C/C++ and the database manipulation capabilities of SQL. It allows you to execute any SQL statement from an application program. Oracle's embedded SQL environment is called Pro*C.&lt;br /&gt;
&lt;br /&gt;
A Pro*C program is compiled in two steps.  First, the Pro*C ''precompiler'' recognizes the SQL statements embedded in the program, and replaces them with appropriate calls to the functions in the SQL runtime library. The output is pure C/C++ code with all the pure C/C++ portions intact. Then, a regular C/C++ compiler is used to compile the code and produces the executable.  For details, see the section on [[yurttas/PL/DBL/oracle/F/R/#demo programs|Demo Programs]].&lt;br /&gt;
&lt;br /&gt;
===---- &amp;lt;font size=&amp;quot;+1&amp;quot;&amp;gt;Pro*C Syntax&amp;lt;/font&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
====---- &amp;lt;font size=&amp;quot;+0&amp;quot;&amp;gt;SQL&amp;lt;/font&amp;gt;====&lt;br /&gt;
&lt;br /&gt;
All SQL statements need to start with &amp;lt;tt&amp;gt;EXEC SQL&amp;lt;/tt&amp;gt; and end with a semicolon &amp;quot;&amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;&amp;quot;. You can place the SQL statements anywhere within a C/C++ block, with the restriction that the declarative statements do not come after the executable statements. As an example:&lt;br /&gt;
&lt;br /&gt;
     {&lt;br /&gt;
         int a;&lt;br /&gt;
         /* ... */&lt;br /&gt;
         EXEC SQL SELECT salary INTO :a&lt;br /&gt;
                  FROM Employee&lt;br /&gt;
                  WHERE SSN=876543210;&lt;br /&gt;
         /* ... */&lt;br /&gt;
         printf(&amp;quot;The salary is %d\n&amp;quot;, a);&lt;br /&gt;
         /* ... */&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
====---- &amp;lt;font size=&amp;quot;+0&amp;quot;&amp;gt;Preprocessor Directives&amp;lt;/font&amp;gt;====&lt;br /&gt;
&lt;br /&gt;
The C/C++ preprocessor directives that work with Pro*C are &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;#if&amp;lt;/tt&amp;gt;. Pro*C does not recognize &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt;. For example, the following code is invalid:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tt&amp;gt;    #define THE_SSN 876543210&lt;br /&gt;
     /* ... */&lt;br /&gt;
     EXEC SQL SELECT salary INTO :a&lt;br /&gt;
              FROM Employee&lt;br /&gt;
              WHERE SSN = THE_SSN;    /* INVALID */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====---- Statement Labels====&lt;br /&gt;
&lt;br /&gt;
You can connect C/C++ labels with SQL as in:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;tt&amp;gt;    EXEC SQL WHENEVER SQLERROR GOTO error_in_SQL;&lt;br /&gt;
     /* ...&amp;lt;/tt&amp;gt; */&lt;br /&gt;
 &amp;lt;tt&amp;gt;error_in_SQL:&lt;br /&gt;
     /* do error handling */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will come to what &amp;lt;tt&amp;gt;WHENEVER&amp;lt;/tt&amp;gt; means later in the section on [[yurttas/PL/DBL/oracle/F/R/#error handling|Error Handling]].&lt;br /&gt;
&lt;br /&gt;
===---- &amp;lt;font size=&amp;quot;+1&amp;quot;&amp;gt;Host Variables&amp;lt;/font&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
====---- Basics====&lt;br /&gt;
&lt;br /&gt;
Host variables are the key to the communication between the host program and the database. A host variable expression must resolve to an ''lvalue'' (''i.e.'', it can be assigned). You can declare host variables according to C syntax, as you declare regular C variables. The host variable declarations can be placed wherever C variable declarations can be placed. (C++ users need to use a ''declare section''; see the section on [[yurttas/PL/DBL/oracle/F/R/#c++ users|C++ Users]].) The C datatypes that can be used with Oracle include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;char[&amp;lt;/tt&amp;gt;''n''&amp;lt;tt&amp;gt;]&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;short&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;long&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;double&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;VARCHAR[&amp;lt;/tt&amp;gt;''n''&amp;lt;tt&amp;gt;]&amp;lt;/tt&amp;gt; - This is a psuedo-type recognized by the Pro*C precompiler. It is used to represent blank-padded, variable-length strings. Pro*C precompiler will convert it into a structure with a 2-byte length field and a ''n''-byte character array.&lt;br /&gt;
&lt;br /&gt;
You cannot use &amp;lt;tt&amp;gt;register&amp;lt;/tt&amp;gt;''' '''storage-class specifier for the host variables.&lt;br /&gt;
&lt;br /&gt;
A host variable reference must be prefixed with a colon &amp;quot;&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;&amp;quot; in SQL statements, but should not be prefixed with a colon in C statements. C function calls and most of the pointer arithmetic expressions ''cannot'' be used as host variable references even though they may indeed resolve to lvalues. The following code illustrates both legal and illegal host variable references:&lt;br /&gt;
&lt;br /&gt;
 int deptnos[3] = { 000, 111, 222 };&lt;br /&gt;
 int get_deptno() { return deptnos[2]; }&lt;br /&gt;
 int *get_deptnoptr() { return &amp;amp;amp;(deptnos[2]); }&lt;br /&gt;
 int main() {&lt;br /&gt;
     int x; char *y; int z;&lt;br /&gt;
     /* ... */&lt;br /&gt;
     EXEC SQL INSERT INTO emp(empno, ename, deptno)&lt;br /&gt;
         VALUES(:x, :y, :z);         /* LEGAL */&lt;br /&gt;
     EXEC SQL INSERT INTO emp(empno, ename, deptno)&lt;br /&gt;
         VALUES(:x + 1,              /* LEGAL: the reference is to x */&lt;br /&gt;
                'Big Shot',          /* LEGAL: but not really a host var */&lt;br /&gt;
                :deptnos[2]);        /* LEGAL: array element is fine */&lt;br /&gt;
     EXEC SQL INSERT INTO emp(empno, ename, deptno)&lt;br /&gt;
         VALUES(:x, :y,&lt;br /&gt;
                :(*(deptnos+2)));    /* ILLEGAL: although it is lvalue */&lt;br /&gt;
     EXEC SQL INSERT INTO emp(empno, ename, deptno)&lt;br /&gt;
         VALUES(:x, :y,&lt;br /&gt;
                :get_deptno());      /* ILLEGAL: no function calls */&lt;br /&gt;
     EXEC SQL INSERT INTO emp(empno, ename, deptno)&lt;br /&gt;
         VALUES(:x, :y,&lt;br /&gt;
                :(*get_depnoptr())); /* ILLEGAL: although it is lvalue */&lt;br /&gt;
     /* ... */&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====---- Pointers====&lt;br /&gt;
&lt;br /&gt;
You can define pointers using the regular C syntax, and use them in embedded SQL statements. As usual, prefix them with a colon:&lt;br /&gt;
&lt;br /&gt;
     int *x;&lt;br /&gt;
     /* ... */&lt;br /&gt;
     EXEC SQL SELECT xyz INTO :x FROM ...;&lt;br /&gt;
&lt;br /&gt;
The result of this &amp;lt;tt&amp;gt;SELECT&amp;lt;/tt&amp;gt; statement will be written into &amp;lt;tt&amp;gt;*x&amp;lt;/tt&amp;gt;, not &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====---- Structures====&lt;br /&gt;
&lt;br /&gt;
Structures can be used as host variables, as illustrated in the following example:&lt;br /&gt;
&lt;br /&gt;
     typedef struct {&lt;br /&gt;
         char name[21];    /* one greater than column length; for '\0' */&lt;br /&gt;
         int SSN;&lt;br /&gt;
     } Emp;&lt;br /&gt;
     /* ... */&lt;br /&gt;
     Emp bigshot;&lt;br /&gt;
     /* ... */&lt;br /&gt;
     EXEC SQL INSERT INTO emp (ename, eSSN)&lt;br /&gt;
         VALUES (:bigshot);&lt;br /&gt;
&lt;br /&gt;
====---- Arrays====&lt;br /&gt;
&lt;br /&gt;
Host arrays can be used in the following way:&lt;br /&gt;
&lt;br /&gt;
     int emp_number[50];&lt;br /&gt;
     char name[50][11];&lt;br /&gt;
     /* ... */&lt;br /&gt;
     EXEC SQL INSERT INTO emp(emp_number, name)&lt;br /&gt;
         VALUES (:emp_number, :emp_name);&lt;br /&gt;
&lt;br /&gt;
which will insert all the 50 tuples in one go.&lt;br /&gt;
&lt;br /&gt;
Arrays can only be single dimensional. The example &amp;lt;tt&amp;gt;char name[50][11]&amp;lt;/tt&amp;gt; would seem to contradict that rule. However, Pro*C actually considers &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; a one-dimensional array of strings rather than a two-dimensional array of characters. You can also have arrays of structures.&lt;br /&gt;
&lt;br /&gt;
When using arrays to store the results of a query, if the size of the host array (say ''n'') is smaller than the actual number of tuples returned by the query, then only the first ''n'' result tuples will be entered into the host array.&lt;br /&gt;
&lt;br /&gt;
====---- Indicator Variables====&lt;br /&gt;
&lt;br /&gt;
Indicator variables are essentially &amp;quot;&amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; flags&amp;quot; attached to host variables. You can associate every host variable with an optional indicator variable. An indicator variable must be defined as a 2-byte integer (using the type &amp;lt;tt&amp;gt;short&amp;lt;/tt&amp;gt;) and, in SQL statements, must be prefixed by a colon and immediately follow its host variable. Or, you may use the keyword &amp;lt;tt&amp;gt;INDICATOR&amp;lt;/tt&amp;gt; in between the host variable and indicator variable. Here is an example:&lt;br /&gt;
&lt;br /&gt;
     short indicator_var;&lt;br /&gt;
     EXEC SQL SELECT xyz INTO :host_var:indicator_var&lt;br /&gt;
         FROM ...;&lt;br /&gt;
     /* ... */&lt;br /&gt;
     EXEC SQL INSERT INTO R&lt;br /&gt;
         VALUES(:host_var INDICATOR :indicator_var, ...);&lt;br /&gt;
&lt;br /&gt;
You can use indicator variables in the &amp;lt;tt&amp;gt;INTO&amp;lt;/tt&amp;gt; clause of a &amp;lt;tt&amp;gt;SELECT&amp;lt;/tt&amp;gt; statement to detect &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;'s or truncated values in the output host variables. The values Oracle can assign to an indicator variable have the following meanings: &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; border=&amp;quot;BORDER&amp;quot;&lt;br /&gt;
| &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt;&lt;br /&gt;
| The column value is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, so the value of the host variable is indeterminate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Oracle assigned an intact column value to the host variable.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Oracle assigned a truncated column value to the host variable. The integer returned by the indicator variable is the original length of the column value.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;-2&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Oracle assigned a truncated column variable to the host variable, but the original column value could not be determined.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;You can also use indicator variables in the &amp;lt;tt&amp;gt;VALUES&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;SET&amp;lt;/tt&amp;gt; clause of an &amp;lt;tt&amp;gt;INSERT&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;UPDATE&amp;lt;/tt&amp;gt;  statement to assign &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;'s to input host variables. The values your program can assign to an indicator variable have the following meanings: &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; border=&amp;quot;BORDER&amp;quot;&lt;br /&gt;
| &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Oracle will assign a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; to the column, ignoring the value of the host variable.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;gt;=0&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Oracle will assign the value of the host variable to the column.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
====---- Datatype Equivalencing====&lt;br /&gt;
&lt;br /&gt;
Oracle recognizes two kinds of datatypes: internal and external. ''Internal datatypes'' specify how Oracle stores column values in database tables. ''External datatypes'' specify the formats used to store values in input and output host variables. At precompile time, a default Oracle external datatype is assigned to each host variable. Datatype equivalencing allows you to override this default equivalencing and lets you control the way Oracle interprets the input data and formats the output data.&lt;br /&gt;
&lt;br /&gt;
The equivalencing can be done on a variable-by-variable basis using the &amp;lt;tt&amp;gt;VAR&amp;lt;/tt&amp;gt; statement. The syntax is:&lt;br /&gt;
&lt;br /&gt;
     EXEC SQL VAR &amp;amp;lt;host_var&amp;amp;gt; IS &amp;amp;lt;type_name&amp;amp;gt; [ (&amp;amp;lt;length&amp;amp;gt;) ];&lt;br /&gt;
&lt;br /&gt;
For example, suppose you want to select employee names from the &amp;lt;tt&amp;gt;emp&amp;lt;/tt&amp;gt; table, and then pass them to a routine that expects C-style &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated strings. You need not explicitly &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminate the names yourself. Simply equivalence a host variable to the &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; external datatype, as follows:&lt;br /&gt;
&lt;br /&gt;
     char emp_name[21];&lt;br /&gt;
     EXEC SQL VAR emp_name IS STRING(21);&lt;br /&gt;
&lt;br /&gt;
The length of the &amp;lt;tt&amp;gt;ename&amp;lt;/tt&amp;gt; column in the &amp;lt;tt&amp;gt;emp&amp;lt;/tt&amp;gt; table is 20 characters, so you allot &amp;lt;tt&amp;gt;emp_name&amp;lt;/tt&amp;gt; 21 characters to accommodate the &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminator. &amp;lt;tt&amp;gt;STRING&amp;lt;/tt&amp;gt; is an Oracle external datatype specifically designed to interface with C-style strings. When you select a value from the &amp;lt;tt&amp;gt;ename&amp;lt;/tt&amp;gt; column into &amp;lt;tt&amp;gt;emp_name&amp;lt;/tt&amp;gt;, Oracle will automatically &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminate the value for you.&lt;br /&gt;
&lt;br /&gt;
You can also equivalence user-defined datatypes to Oracle external datatypes using the &amp;lt;tt&amp;gt;TYPE&amp;lt;/tt&amp;gt; statement. The syntax is:&lt;br /&gt;
&lt;br /&gt;
     EXEC SQL TYPE &amp;amp;lt;user_type&amp;amp;gt; IS &amp;amp;lt;type_name&amp;amp;gt; [ (&amp;amp;lt;length&amp;amp;gt;) ] [REFERENCE];&lt;br /&gt;
&lt;br /&gt;
You can declare a user-defined type to be a pointer, either explicitly, as a pointer to a scalar or structure, or implicitly as an array, and then use this type in a &amp;lt;tt&amp;gt;TYPE&amp;lt;/tt&amp;gt; statement. In these cases, you need to use the &amp;lt;tt&amp;gt;REFERENCE&amp;lt;/tt&amp;gt; clause at the end of the statement, as shown below:&lt;br /&gt;
&lt;br /&gt;
     typedef unsigned char *my_raw;&lt;br /&gt;
     EXEC SQL TYPE my_raw IS VARRAW(4000) REFERENCE;&lt;br /&gt;
     my_raw buffer;&lt;br /&gt;
     /* ... */&lt;br /&gt;
     buffer = malloc(4004);&lt;br /&gt;
&lt;br /&gt;
Here we allocated more memory than the type length (4000) because the precompiler also returns the length, and may add padding after the length in order to meet the alignment requirement on your system.&lt;br /&gt;
&lt;br /&gt;
===---- &amp;lt;font size=&amp;quot;+1&amp;quot;&amp;gt;Error Handling&amp;lt;/font&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
After each executable SQL statement, your program can find the status of execution either by explicit checking of SQLCA, or by implicit checking using the &amp;lt;tt&amp;gt;WHENEVER&amp;lt;/tt&amp;gt; statement. These two ways are covered in details below.&lt;br /&gt;
&lt;br /&gt;
====---- SQLCA====&lt;br /&gt;
&lt;br /&gt;
SQLCA (SQL Communications Area) is used to detect errors and status changes in your program. This structure contains components that are filled in by Oracle at runtime after every executable SQL statement.&lt;br /&gt;
&lt;br /&gt;
To use SQLCA you need to include the header file &amp;lt;tt&amp;gt;sqlca.h&amp;lt;/tt&amp;gt; using the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive. In case you need to include &amp;lt;tt&amp;gt;sqlca.h&amp;lt;/tt&amp;gt; at many places, you need to first undefine the macro &amp;lt;tt&amp;gt;SQLCA&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;#undef SQLCA&amp;lt;/tt&amp;gt;. The relevant chunk of &amp;lt;tt&amp;gt;sqlca.h&amp;lt;/tt&amp;gt; follows:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#ifndef SQLCA&lt;br /&gt;
 #define SQLCA 1&lt;br /&gt;
 &lt;br /&gt;
 struct sqlca {&lt;br /&gt;
     /* ub1 */ char sqlcaid[8];&lt;br /&gt;
     /* b4 */ long sqlabc;&lt;br /&gt;
     /* b4 */ long sqlcode;&lt;br /&gt;
     struct {&lt;br /&gt;
         /* ub2 */ unsigned short sqlerrml;&lt;br /&gt;
         /* ub1 */ char sqlerrmc[70];&lt;br /&gt;
     } sqlerrm;&lt;br /&gt;
     /* ub1 */ char sqlerrp[8];&lt;br /&gt;
     /* b4 */ long sqlerrd[6];&lt;br /&gt;
     /* ub1 */ char sqlwarn[8];&lt;br /&gt;
     /* ub1 */ char sqlext[8];&lt;br /&gt;
 };&lt;br /&gt;
 /* ... */&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fields in &amp;lt;tt&amp;gt;sqlca&amp;lt;/tt&amp;gt; have the following meaning: &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; border=&amp;quot;BORDER&amp;quot;&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlcaid&amp;lt;/tt&amp;gt;&lt;br /&gt;
| This string component is initialized to &amp;quot;SQLCA&amp;quot; to identify the SQL Communications Area.  &amp;lt;br /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlcabc&amp;lt;/tt&amp;gt;&lt;br /&gt;
| This integer component holds the length, in bytes, of the SQLCA structure.  &amp;lt;br /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlcode&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
This integer component holds the status code of the most recently executed SQL statement:  &amp;lt;br /&amp;gt;  &amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;90%&amp;quot; border=&amp;quot;BORDER&amp;quot;&lt;br /&gt;
| &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
| No error.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Statement executed but exception detected. This occurs when Oracle cannot find a row that meets your &amp;lt;tt&amp;gt;WHERE&amp;lt;/tt&amp;gt; condition or when a &amp;lt;tt&amp;gt;SELECT INTO&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FETCH&amp;lt;/tt&amp;gt; returns no rows.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;amp;lt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Oracle did not execute the statement because of an error. When such errors occur, the current transaction should, in most cases, be rolled back.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlerrm&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
This embedded structure contains the following two components: &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrml&amp;lt;/tt&amp;gt; - Length of the message text stored in &amp;lt;tt&amp;gt;sqlerrmc&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrmc&amp;lt;/tt&amp;gt; - Up to 70 characters of the message text corresponding to the error code stored in &amp;lt;tt&amp;gt;sqlcode&amp;lt;/tt&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlerrp&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Reserved for future use.  &amp;lt;br /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlerrd&amp;lt;/tt&amp;gt;&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; |&lt;br /&gt;
This array of binary integers has six elements: &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrd[0]&amp;lt;/tt&amp;gt; - Future use.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrd[1]&amp;lt;/tt&amp;gt; - Future use.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrd[2]&amp;lt;/tt&amp;gt; - Numbers of rows processed by the most recent SQL statement.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrd[3]&amp;lt;/tt&amp;gt; - Future use.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrd[4]&amp;lt;/tt&amp;gt; - Offset that specifies the character position at which a parse error begins in the most recent SQL statement.&lt;br /&gt;
* &amp;lt;tt&amp;gt;sqlerrd[5]&amp;lt;/tt&amp;gt; - Future use.&amp;lt;br /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlwarn&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
This array of single characters has eight elements used as warning flags. Oracle sets a flag by assigning to it the character &amp;lt;tt&amp;gt;'W'&amp;lt;/tt&amp;gt;.  &amp;lt;br /&amp;gt;  &amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;90%&amp;quot; border=&amp;quot;BORDER&amp;quot;&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[0]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Set if any other flag is set.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[1]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Set if a truncated column value was assigned to an output host variable.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[2]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Set if a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; column value is not used in computing a SQL aggregate such as &amp;lt;tt&amp;gt;AVG&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SUM&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[3]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Set if the number of columns in &amp;lt;tt&amp;gt;SELECT&amp;lt;/tt&amp;gt; does not equal the number of host variables specified in &amp;lt;tt&amp;gt;INTO&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[4]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Set if every row in a table was processed by an &amp;lt;tt&amp;gt;UPDATE&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DELETE&amp;lt;/tt&amp;gt; statement without a &amp;lt;tt&amp;gt;WHERE&amp;lt;/tt&amp;gt; clause.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[5]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Set if a procedure/function/package/package body creation command fails because of a PL/SQL compilation error.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[6]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| No longer in use.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sqlwarn[7]&amp;lt;/tt&amp;gt;&lt;br /&gt;
| No longer in use.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| valign=&amp;quot;TOP&amp;quot; | &amp;lt;tt&amp;gt;sqlext&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Reserved for future use.  &amp;lt;br /&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''' '''&amp;lt;br /&amp;gt;SQLCA can only accommodate error messages up to 70 characters long in its &amp;lt;tt&amp;gt;sqlerrm&amp;lt;/tt&amp;gt; component. To get the full text of longer (or nested) error messages, you need the &amp;lt;tt&amp;gt;sqlglm()&amp;lt;/tt&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
     void sqlglm(char *msg_buf, size_t *buf_size, size_t *msg_length);&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;msg_buf&amp;lt;/tt&amp;gt; is the character buffer in which you want Oracle to store the error message; &amp;lt;tt&amp;gt;buf_size&amp;lt;/tt&amp;gt; specifies the size of &amp;lt;tt&amp;gt;msg_buf&amp;lt;/tt&amp;gt; in bytes; Oracle stores the actual length of the error message in &amp;lt;tt&amp;gt;*msg_length&amp;lt;/tt&amp;gt;. The maximum length of an Oracle error message is 512 bytes.&lt;br /&gt;
&lt;br /&gt;
====---- WHENEVER Statement====&lt;br /&gt;
&lt;br /&gt;
This statement allows you to do automatic error checking and handling. The syntax is:&lt;br /&gt;
&lt;br /&gt;
     EXEC SQL WHENEVER &amp;amp;lt;condition&amp;amp;gt; &amp;amp;lt;action&amp;amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Oracle automatically checks SQLCA for &amp;lt;tt&amp;gt;&amp;amp;lt;condition&amp;amp;gt;&amp;lt;/tt&amp;gt;, and if such condition is detected, your program will automatically perform &amp;lt;tt&amp;gt;&amp;amp;lt;action&amp;amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;condition&amp;amp;gt;&amp;lt;/tt&amp;gt; can be any of the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;SQLWARNING&amp;lt;/tt&amp;gt; - &amp;lt;tt&amp;gt;sqlwarn[0]&amp;lt;/tt&amp;gt; is set because Oracle returned a warning&lt;br /&gt;
* &amp;lt;tt&amp;gt;SQLERROR&amp;lt;/tt&amp;gt; - &amp;lt;tt&amp;gt;sqlcode&amp;lt;/tt&amp;gt; is negative because Oracle returned an error&lt;br /&gt;
* &amp;lt;tt&amp;gt;NOT FOUND&amp;lt;/tt&amp;gt; - &amp;lt;tt&amp;gt;sqlcode&amp;lt;/tt&amp;gt; is positive because Oracle could not find a row that meets your &amp;lt;tt&amp;gt;WHERE&amp;lt;/tt&amp;gt; condition, or a &amp;lt;tt&amp;gt;SELECT INTO&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;FETCH&amp;lt;/tt&amp;gt; returned no rows&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;lt;action&amp;amp;gt;&amp;lt;/tt&amp;gt; can be any of the following:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;CONTINUE&amp;lt;/tt&amp;gt; - Program will try to continue to run with the next statement if possible&lt;br /&gt;
* &amp;lt;tt&amp;gt;DO&amp;lt;/tt&amp;gt; - Program transfers control to an error handling function&lt;br /&gt;
* &amp;lt;tt&amp;gt;GOTO &amp;amp;lt;label&amp;amp;gt;&amp;lt;/tt&amp;gt;'' ''- Program branches to a labeled statement&lt;br /&gt;
* &amp;lt;tt&amp;gt;STOP&amp;lt;/tt&amp;gt; - Program exits with an &amp;lt;tt&amp;gt;exit()&amp;lt;/tt&amp;gt; call, and uncommitted work is rolled back&lt;br /&gt;
&lt;br /&gt;
Some examples of the &amp;lt;tt&amp;gt;WHENEVER&amp;lt;/tt&amp;gt; statement:&lt;br /&gt;
&lt;br /&gt;
     EXEC SQL WHENEVER SQLWARNING DO print_warning_msg();&lt;br /&gt;
     EXEC SQL WHENEVER NOT FOUND GOTO handle_empty;&lt;br /&gt;
&lt;br /&gt;
Here is a more concrete example:&lt;br /&gt;
&lt;br /&gt;
 /* code to find student name given id */&lt;br /&gt;
 /* ... */&lt;br /&gt;
 for (;;) {&lt;br /&gt;
     printf(&amp;quot;Give student id number : &amp;quot;);&lt;br /&gt;
     scanf(&amp;quot;%d&amp;quot;, &amp;amp;amp;id);&lt;br /&gt;
     EXEC SQL WHENEVER NOT FOUND GOTO notfound;&lt;br /&gt;
     EXEC SQL SELECT studentname INTO :st_name&lt;br /&gt;
              FROM   student&lt;br /&gt;
              WHERE  studentid = :id;&lt;br /&gt;
     printf(&amp;quot;Name of student is %s.\n&amp;quot;, st_name);&lt;br /&gt;
     continue;&lt;br /&gt;
 notfound:&lt;br /&gt;
     printf(&amp;quot;No record exists for id %d!\n&amp;quot;, id);&lt;br /&gt;
 }&lt;br /&gt;
 /* ... */&lt;br /&gt;
&lt;br /&gt;
===---- &amp;lt;font size=&amp;quot;+1&amp;quot;&amp;gt;Demo Programs&amp;lt;/font&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
'''Note:''' The demo programs will create and use four tables named &amp;lt;tt&amp;gt;DEPT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;EMP&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PAY1&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;PAY2&amp;lt;/tt&amp;gt;. Be careful if any table in your PDA happens to have the same name!&lt;br /&gt;
&lt;br /&gt;
Several demo programs are available in &amp;lt;tt&amp;gt;/usr/class/cs145/code/proc&amp;lt;/tt&amp;gt; on the leland system. They are named &amp;lt;tt&amp;gt;sample*.pc&amp;lt;/tt&amp;gt; (for C users) and &amp;lt;tt&amp;gt;cppdemo*.pc&amp;lt;/tt&amp;gt; (for C++ users). &amp;quot;&amp;lt;tt&amp;gt;.pc&amp;lt;/tt&amp;gt;&amp;quot; is the extension for Pro*C code. Do ''not'' copy these files manually, since there are a couple of customizations to do. To download and customize the demo programs, follow the instructions below:&lt;br /&gt;
&lt;br /&gt;
# Make sure that you have run &amp;lt;tt&amp;gt;source /usr/class/cs145/cora.env&amp;lt;/tt&amp;gt;&lt;br /&gt;
# In your home directory, run &amp;lt;tt&amp;gt;load_samples &amp;amp;lt;db_username&amp;amp;gt; &amp;amp;lt;db_passwd&amp;amp;gt; &amp;amp;lt;sample_dir&amp;amp;gt;&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;&amp;amp;lt;sample_dir&amp;amp;gt;&amp;lt;/tt&amp;gt; is the name of the directory where you wish to put demo programs (''e.g.'', &amp;lt;tt&amp;gt;load_samples sally etaoinshrdlu cs145_samples&amp;lt;/tt&amp;gt;)&lt;br /&gt;
# &amp;lt;tt&amp;gt;cd &amp;amp;lt;sample_dir&amp;amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
# Run &amp;lt;tt&amp;gt;make samples&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;make cppsamples&amp;lt;/tt&amp;gt; for C++) to compile all demo programs&lt;br /&gt;
&lt;br /&gt;
Step (2) will set up the sample database, create a new directory as specified in &amp;lt;tt&amp;gt;&amp;amp;lt;sample_dir&amp;amp;gt;&amp;lt;/tt&amp;gt;, and copy the demo files into that directory. It will also change the user name and password in the sample programs to be yours, so that you do not have to type in your username and password every time when running a sample program. However, &amp;lt;tt&amp;gt;sample1&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;cppdemo1&amp;lt;/tt&amp;gt; do provide an interface for the user to input the username and password, in case you would like to learn how to do it.&lt;br /&gt;
&lt;br /&gt;
If you happen to make any mistake when entering username or password in Step (2), just run &amp;lt;tt&amp;gt;clean_samples &amp;amp;lt;db_username&amp;amp;gt; &amp;amp;lt;db_passwd&amp;amp;gt; &amp;amp;lt;sample_dir&amp;amp;gt;&amp;lt;/tt&amp;gt; in your home directory, and then repeat Steps (2) to (4).&lt;br /&gt;
&lt;br /&gt;
For Step (4), you can also compile each sample program separately. For example, &amp;lt;tt&amp;gt;make sample1&amp;lt;/tt&amp;gt; compiles &amp;lt;tt&amp;gt;sample1.pc&amp;lt;/tt&amp;gt; alone. The compilation process actually has two phases:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;tt&amp;gt;proc iname=sample1.pc&amp;lt;/tt&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;tt&amp;gt;sample1.c&amp;lt;/tt&amp;gt;&lt;br /&gt;
# &amp;lt;tt&amp;gt;cc &amp;amp;lt;a_number_of_flags_here&amp;amp;gt; sample1.c&amp;lt;/tt&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;tt&amp;gt;sample1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To compile your own code, say, &amp;lt;tt&amp;gt;foo.pc&amp;lt;/tt&amp;gt;, just change a few variables in &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt;: Add the program name &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; to variable &amp;lt;tt&amp;gt;SAMPLES&amp;lt;/tt&amp;gt; and the source file name &amp;lt;tt&amp;gt;foo.pc&amp;lt;/tt&amp;gt; to variable &amp;lt;tt&amp;gt;SAMPLE_SRC&amp;lt;/tt&amp;gt;. Then, do &amp;lt;tt&amp;gt;make foo&amp;lt;/tt&amp;gt; after &amp;lt;tt&amp;gt;foo.pc&amp;lt;/tt&amp;gt; is ready. &amp;lt;tt&amp;gt;foo.pc&amp;lt;/tt&amp;gt; will be precompiled to &amp;lt;tt&amp;gt;foo.c&amp;lt;/tt&amp;gt; and then compiled to &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt;, the executable. C++ users will need to add their program name to &amp;lt;tt&amp;gt;CPPSAMPLES&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;SAMPLES&amp;lt;/tt&amp;gt;, and source file name to &amp;lt;tt&amp;gt;CPPSAMPLE_SRC&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;SAMPLE_SRC&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The demo programs operate on the following tables:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE DEPT&lt;br /&gt;
     (DEPTNO    NUMBER(2) NOT NULL,&lt;br /&gt;
      DNAME     VARCHAR2(14),&lt;br /&gt;
      LOC       VARCHAR2(13));&lt;br /&gt;
 &lt;br /&gt;
 CREATE TABLE EMP&lt;br /&gt;
     (EMPNO     NUMBER(4) NOT NULL,&lt;br /&gt;
      ENAME     VARCHAR2(10),&lt;br /&gt;
      JOB       VARCHAR2(9),&lt;br /&gt;
      MGR       NUMBER(4),&lt;br /&gt;
      HIREDATE  DATE,&lt;br /&gt;
      SAL       NUMBER(7, 2),&lt;br /&gt;
      COMM      NUMBER(7, 2),&lt;br /&gt;
      DEPTNO    NUMBER(2));&lt;br /&gt;
 &lt;br /&gt;
 CREATE TABLE PAY1&lt;br /&gt;
     (ENAME     VARCHAR2(10),&lt;br /&gt;
      SAL       NUMBER(7, 2));&lt;br /&gt;
 &lt;br /&gt;
 CREATE TABLE PAY2&lt;br /&gt;
     (ENAME     VARCHAR2(10),&lt;br /&gt;
      SAL       NUMBER(7, 2));&lt;br /&gt;
&lt;br /&gt;
These tables are created automatically when you run &amp;lt;tt&amp;gt;load_samples&amp;lt;/tt&amp;gt; in Step (2). A few tuples are also inserted. You may like to browse the tables before running the samples on them. You can also play with them as you like (''e.g.'', inserting, deleting, or updating tuples). These tables will be dropped automatically when you run &amp;lt;tt&amp;gt;clean_samples&amp;lt;/tt&amp;gt;. '''Note:''' &amp;lt;tt&amp;gt;clean_samples&amp;lt;/tt&amp;gt; also wipes out the entire &amp;lt;tt&amp;gt;&amp;amp;lt;sample_dir&amp;amp;gt;&amp;lt;/tt&amp;gt;; make sure you move your own files to some other place before running this command!&lt;br /&gt;
&lt;br /&gt;
You should take a look at the sample source code before running it. The comments at the top describe what the program does. For example, &amp;lt;tt&amp;gt;sample1&amp;lt;/tt&amp;gt; takes an employee's &amp;lt;tt&amp;gt;EMPNO&amp;lt;/tt&amp;gt; and retrieve the name, salary, and commission for that employee from the table &amp;lt;tt&amp;gt;EMP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You are supposed to study the sample source code and learn the following:&lt;br /&gt;
&lt;br /&gt;
* How to connect to Oracle from the host program&lt;br /&gt;
* How to embed SQL in C/C++&lt;br /&gt;
* How to use cursors&lt;br /&gt;
* How to use host variables to communicate with the database&lt;br /&gt;
* How to use &amp;lt;tt&amp;gt;WHENEVER&amp;lt;/tt&amp;gt; to take different actions on error messages&lt;br /&gt;
* How to use indicator variables to detect &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;'s in the output&lt;br /&gt;
&lt;br /&gt;
Now, you can use these techniques to code your own PDA interface program. And have fun!&lt;br /&gt;
&lt;br /&gt;
===---- &amp;lt;font size=&amp;quot;+1&amp;quot;&amp;gt;C++ Users&amp;lt;/font&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
To get the precompiler to generate appropriate C++ code, you need to be aware of the following issues:&lt;br /&gt;
&lt;br /&gt;
* Code emission by precompiler. To get C++ code, you need to set the option &amp;lt;tt&amp;gt;CODE=CPP&amp;lt;/tt&amp;gt; while executing &amp;lt;tt&amp;gt;proc&amp;lt;/tt&amp;gt;. C users need not worry about this option; the default caters to their needs.&lt;br /&gt;
&lt;br /&gt;
* Parsing capability. The &amp;lt;tt&amp;gt;PARSE&amp;lt;/tt&amp;gt; option of &amp;lt;tt&amp;gt;proc&amp;lt;/tt&amp;gt; may take the following values:&lt;br /&gt;
&lt;br /&gt;
** &amp;lt;tt&amp;gt;PARSE=NONE&amp;lt;/tt&amp;gt;. C preprocessor directives are understood only inside a declare section, and all host variables need to be declared inside a declare section.&lt;br /&gt;
** &amp;lt;tt&amp;gt;PARSE=PARTIAL&amp;lt;/tt&amp;gt;. C preprocessor directives are understood; however, all host variables need to be declared inside a declare section.&lt;br /&gt;
** &amp;lt;tt&amp;gt;PARSE=FULL&amp;lt;/tt&amp;gt;. C preprocessor directives are understood and host variables can be declared anywhere. This is the default when &amp;lt;tt&amp;gt;CODE&amp;lt;/tt&amp;gt; is anything other than &amp;lt;tt&amp;gt;CPP&amp;lt;/tt&amp;gt;; it is an error to specify &amp;lt;tt&amp;gt;PARSE=FULL&amp;lt;/tt&amp;gt; with &amp;lt;tt&amp;gt;CODE=CPP&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;PARSE=NONE&amp;lt;/tt&amp;gt;&amp;lt;tt&amp;gt;PARSE=PARTIAL&amp;lt;/tt&amp;gt;''declare sections''     EXEC SQL BEGIN DECLARE SECTION;&lt;br /&gt;
         // declarations...&lt;br /&gt;
     EXEC SQL END DECLARE SECTION;&lt;br /&gt;
&lt;br /&gt;
* File extension. You need to specify the option &amp;lt;tt&amp;gt;CPP_SUFFIX=cc&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;CPP_SUFFIX=C&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Location of header files. By default, &amp;lt;tt&amp;gt;proc&amp;lt;/tt&amp;gt; searches for header files like &amp;lt;tt&amp;gt;stdio.h&amp;lt;/tt&amp;gt; in standard locations. However, C++ has its own header files, such as &amp;lt;tt&amp;gt;iostream.h&amp;lt;/tt&amp;gt;, located elsewhere. So you need to use the &amp;lt;tt&amp;gt;SYS_INCLUDE&amp;lt;/tt&amp;gt; option to specify the paths that &amp;lt;tt&amp;gt;proc&amp;lt;/tt&amp;gt; should search for header files.&lt;br /&gt;
&lt;br /&gt;
===---- &amp;lt;font size=&amp;quot;+1&amp;quot;&amp;gt;List of Embedded SQL Statements Supported by Pro*C&amp;lt;/font&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; border=&amp;quot;BORDER&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; align=&amp;quot;CENTER&amp;quot; | '''Declarative Statements'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL ARRAYLEN&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To use host arrays with PL/SQL&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL BEGIN DECLARE SECTION&amp;lt;/tt&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;tt&amp;gt;EXEC SQL END DECLARE SECTION&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To declare host variables&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL DECLARE&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To name Oracle objects&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL INCLUDE&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To copy in files&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL TYPE&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To equivalence datatypes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL VAR&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To equivalence variables&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL WHENEVER&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To handle runtime errors&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; align=&amp;quot;CENTER&amp;quot; | '''Executable Statements'''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL ALLOCATE&amp;lt;/tt&amp;gt;&lt;br /&gt;
| rowspan=&amp;quot;14&amp;quot; | To define and control Oracle data&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL ALTER&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL ANALYZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL AUDIT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL COMMENT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL CONNECT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL CREATE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL DROP&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL GRANT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL NOAUDIT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL RENAME&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL REVOKE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL TRUNCATE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL CLOSE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL DELETE&amp;lt;/tt&amp;gt;&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | To query and manipulate Oracle data&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL EXPLAIN PLAN&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL FETCH&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL INSERT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL LOCK TABLE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL OPEN&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL SELECT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL UPDATE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL COMMIT&amp;lt;/tt&amp;gt;&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | To process transactions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL ROLLBACK&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL SAVEPOINT&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL SET TRANSACTION&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL DESCRIBE&amp;lt;/tt&amp;gt;&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | To use dynamic SQL&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL EXECUTE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL PREPARE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL ALTER SESSION&amp;lt;/tt&amp;gt;&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | To control sessions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL SET ROLE&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;EXEC SQL EXECUTE&amp;lt;/tt&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;tt&amp;gt;END-EXEC&amp;lt;/tt&amp;gt;&lt;br /&gt;
| To embed PL/SQL blocks&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;-2&amp;quot;&amp;gt;This document is written originally for Prof. Jeff Ullman's CS145 class in Autumn, 1997; revised by Jun Yang for Prof. Jennifer Widom's CS145 class in Spring, 1998.&amp;lt;/font&amp;gt;&lt;/div&gt;</summary>
		<author><name>MassBot1</name></author>
	</entry>
</feed>