You are on page 1of 18

Table of Contents

1. 2. 3. Introduction to pro *c. Use of PROCEDURAL interfaces. Elements of program. 3.1 Application Prologue: 3.1.1 Declare section 3.1.2 SQLCA 3.1.3 Connecting to ORACLE 3.2 Application Body 3.2.1 Data Manipulation 3.2.2 Data Retrieval 3.2.3 Dynamic statements. Error handling. User exits.

4. 5.

PRO * C

Page 1 of 18

Introduction
SQL is a non-procedural language. Although it is very powerful SQL has some limitations without procedural capabilities . The SQL designers made provisions for embedding SQL constructs in procedural languages such as COBOL,C etc..... With these the best features of SQL and the programming language(host language) can be utilized. The Precompiler converts a High language program with SQL statements into a normal program which can access and manipulate date in an oracle database. It is a Pre-compiler which converts the SQL statements in its input file to appropriate ORACLE calls in an output file. This output file can be compiled, linked and executed as any other program. All SQL statements must begin with EXEC SQL in all these Procedural languages. It must end with END EXEC .All the host languages syntax and rules hold for these embedded SQL statements also. Use of Procedural Interfaces As a stand alone software program to access and manipulate on ORACLE Database. As a supplement to SQL*FORMS this is to increase the capability of the user designed software in performing validation, additional queries etc. If used in this manner it is called as USER-EXIT.

Elements of PRO *C program 1. Application prologue: 2. DECLARE section INCLUDE SQLCA ---- to name the SQL communication Area. CONNECT statement --- to connect to the ORACLE database.

Application body: Data Manipulation statements Data Retrieval statements Dynamic statements.

PRO * C

Page 2 of 18

3.1 Application Prologue 3.1.1 DECLARE section: * All host variables that hold database data i.e... referenced in SQL statements and

indicator variables which are used to deal with null values are declared here. * Only one DECLARE section is allowed per pre-compiled unit. * A program can have many independent precompiled units. * The DECLARE section can appear globally or within a local function. FORMAT : EXEC SQL BEGIN DECLARE SECTION; list of declarations EXEC SQL END DECLARE SECTION; Host Variable * * * * * * EX: EXEC SQL BEGIN DECLARE SECTION; int emp_no; char emp_name[20]; varchar emp_desc; EXEC SQL END DECLARE SECTION; varchar is a PSEUDO-TYPE to accommodate variable length character strings. Indicator Variables: * * * * * Indicator variables have one-to-one correspondence with host variables. Are primarily for dealing with NULL values. They contain return codes which may be null value returned or character field truncated. Must be explicitly declared in DECLARE section. Case sensitive . Must be SHORT INT.
Page 3 of 18

Must be explicitly declare in the DECLARE section. Is case sensitive in usage. Preceded by a : only in the SQL statement. Must not be a SQL reserved word. Can only be used where a constant can be used. Can be a POINTER variable.

PRO * C

* * * ex:

Preceded by a : when used in SQL Must not be a SQL reserved word. Must be preceded by its associated host variable.

EXEC SQL SELECT ENAME INTO :emp_name:enameno EMPNO=:emp_no; Here enameno is an indicator variable. SQLCA * * * * *

FROM

EMP WHERE

SQLCA is the SQL Communication Area. It is used to pass information about the execution of the program. The scope of a SQLCA is limited by the restrictions of the host language. The SQLCA is updated after every executable statement. Including SQLCA into the program:

FORMAT: EXEC SQL INCLUDE SQLCA; EXEC SQL INCLUDE can also be used to include other files into the Pro*C program. Connecting to ORACLE Connecting is done using the CONNECT Used only in stand alone PRO*C programs. Must be the first eexecutable SQL statement. Host variables can be used to pass username statement.

and the password.

FORMAT: EXEC SQL CONNECT :oracleid IDENTIFIED BY :oraclepasswd; or EXEC SQL CONNECT :usr IDENTIFIED BY :pwd;

PRO * C

Page 4 of 18

The Application Body The Application body contains SQL statements to query and manipulate data stored in an ORACLE database . It may also contain statements to create, delete and define data. In this document we first discuss SQL statements to INSERT,UPDATE,DELETE and CREATE. They are relatively easy to understand ,because the dont return rows of data only a success code. NOTE: After each access to the Data base,if the Data base is to be altered, the WORK HAS TO BE COMMITED. Data Manipulation Statements Insert To insert data into a table use the normal SQL statement with EXEC SQL preceding it. FORMAT EXEC SQL INSERT INTO EMP (EMPNO,EMP_NAME) VALUES(:empno,:empname); Update Updation is similiar to insertion. FORMAT EXEC SQL UPDATE EMP SET EMP_NO=3333 WHERE EMP_NO=2222; Delete FORMAT EXEC SQL DELETE FROM EMP; Create FORMAT EXEC SQL CREATE TABLE EMP.......

PRO * C

Page 5 of 18

Drop FORMAT EXEC SQL DROP TABLE EMP; Use of Arrays: PRO Languages accept host variables declared as arrays for use in INSERT,UPDATE AND SELECT statements. Insert, Update and Select are done in the normal way, but instead of operating on single records they operate on an array of records. When used in SELECT statement, the where clause should never contain an array. When used in UPDATE statement SET clause is valid only if the WHERE clause also operates on an array. Host arrays must not be subscripted in SQL statements.

FORMAT EXEC SQL BEGIN DECLARE SECTION: char ename[100][25]; EXEC SQL END DECLARE SECTION (END-EXEC); EXEC SQL UPDATE EMP SET sal=:sal WHERE (:ename,....); Commit After each database manipulation the work has to be committed in order to alter the database. Unless committed the database is not altered. This is done using the COMMIT statement. This also ends a logical unit of work. Commits the work and logs off database. COMMIT WORK has no effect on the contents of the most variables or on the control flow of the program. Every DDL statement such as CREATE or DROP issues on automatic COMMIT WORK.

FORMAT
PRO * C Page 6 of 18

EXEC SQL COMMIT WORK RELEASE; Rollback The ROLLBACK statement ends the current logical unit of CHANGES mode during that unit of work. work, and UNDOES all

ROLLBACK WORK has no effect on the contents of the host variables or on the control flow of the program. ORACLE automatically commits pending changes on successful termination of the program. If the program terminates ABNORMALLY it will ROLLBACK changes.

FORMAT EXEC SQL ROLLBACK WORK(END-EXEC) Rollsback the work EXEC SQL ROLLBACK WORK RELEASE(END-EXEC); Rolls back and LOGS OFF database. Data Retrieval statements Queries coded in PRO*C may contain any SQL SELECT statement In addition to the keywords used in SQL*PLUS a keyword INTO can be used. The variable following the keyword INTO holds the data selected from the database.

Queries in PRO*C can be classified as 1.Returning a SINGLE ROW. 2.Returning MANY rows. Queries returning a single row. FORMAT SELECT ENAME,EMP_NO INTO :emp_name,:emp_no FROM EMP WHERE EMP_NO=2222; Queries returning multiple rows If the query may return more than one row, use a CURSOR along with the SELECT statement. Cursors
PRO * C Page 7 of 18

A Cursor is a work area used by oracle and

pro*c to store the results of a query.

One cursor is associated with one select statement and can be used repeatedly for different variations of the query.

There are four cursor commands 1. DECLARE CURSOR 2. OPEN CURSOR 3. FETCH 4. CLOSE CURSOR A cursor is first declared. After opening cursor use it to retrieve rows. Rows are returned one by one by fetching them. When the query is done the cursor is closed.

Declare cursor The DECLARE CURSOR statement defines a cursor, by assigning it a name and associating it with a query.

FORMAT EXEC SQL DECLARE cursorname CURSOR FOR SELECT ............FROM .......... This statement must occur before any SQL statement refers it. The scope of the cursor is the entire program. But all the cursor statements DECLARE, OPEN, FETCH, CLOSE must all occur within the same precompiled unit. A program can have as many cursors as queries. Every DECLARE statement must be UNIQUE.

Open cursor By opening a cursor, the query is evaluated and the active set of rows identified.

FORMAT EXEC SQL OPEN cursorname The host variables in the WHERE clause are evaluated. To change any host variable and hence the query condition the cursor must be reopened.
Page 8 of 18

PRO * C

Fetch This statement reads the rows of the active set. FORMAT EXEC SQL FETCH cursorname INTO :hostvarl,..........,:hostvarn; The first time FETCH is executed ,the first row is fetched. Each subsequent FETCH calls retrieve subsequent rows matching the query condition. The cursor can move only FORWARD. The only way to return to a row previously fetched is to close and re-open the cursor and begin again from the first. If there are no more rows to fetch the SQLCODE is set to 41403.

CLOSE The cursor should be closed to release all the resources. FORMAT EXEC SQL CLOSE cursorname Dynamically defined statement. Dynamic SQL statement are SQL statements known only at execution time. They are constructed using the text entered by the user. There are four types 1. Execute immediate 2. Prepare and Execute. 3. Prepare and Fetch. 4. Using Bind and define descriptors. If the SQL statement is a QUERY use only the THIRD or the FOURTH method. The input from user must not contain host language delimiters must not be prefixed by EXEC SQL may contain host language variables. Execute Immediate Can be used when the program reads, precompiles and executes a SQL statement. The statement must not be a query. The statement must not contain any host variables. Can be executed only once with a single parameter.

FORMAT
PRO * C Page 9 of 18

EXEC SQL BEGIN DECLARE SECTION; VARCHAR mystring[80]; EXEC SQL END DECLARE SECTION ; scanf(%s,mystring.arr); EXEC SQL EXECUTE IMMEDIATE :mystring; or EXEC SQL EXECUTE IMMEDIATE DELETE FROM EMP WHERE EMPNO=2224; Prepare and Execute Can be prepared once and executed many times. Can contain host variables

Involves two steps 1. parsing the SQL statement 2. a name is given to the SQL statement. If the current transaction has been commited or rolledback the SQL statement has to be prepared again. The number of parameters and their data types must be known.

FORMAT: EXEC SQL PREPARE s1 FROM :selstring; EXEC SQL EXECUTE s1 USING :comm; s1 is a cursor ; selstring is a string which holds the sql statement. eg: UPDATE.........; comm is a host variable. Prepare Open and Fetch:

Similar to above but is highly flexible . Used for preprogrammed and non dynamic queries.

FORMAT Involves five steps: 1.Prepare EXEC SQL PREPARE statementname FROM select statement. 2.declare: EXEC SQL DECLARE cursorname CURSOR FOR 3.Open:
PRO * C

statementname.
Page 10 of 18

EXEC SQL OPEN cursorname ; 4.Fetch: EXEC SQL FETCH cursorname INTO 5.Close: EXEC SQL CLOSE cursorname. Error Handling

variables;

PRO*C continues to process regardless of errors . The WHENEVER statement is used to trap errors and to take necessary action.

FORMAT: EXEC SQL WHENEVER [SQLERROR | SQLWARNING [ NOTFOUND] [STOP |CONTINUE [ GOTO label]

Error checking can also be explicitly done by checking the contents of SQLCA.

Logging in and out of Oracle: The first example is the most basic PRO*C program. EXAMPLE #1 #include<stdio.h> EXEC SQL BEGIN DECLARE SECTION; VARCHAR uid [20]; VARCHAR pwd[20]; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; main() { strcpy(uid.arr,SCOTT); uid.len=strlen(uid.arr); strcpy(pwd.arr,TIGER); pwd.len=strlen(pwd.arr); EXEC SQL CONNECT:uid IDENTIFIED BY :pwd; printf(Connected to Oracle user %s ,uid.arr); EXEC SQL COMMIT WORK RELEASE; exit(0);} EXAMPLE #2
PRO * C Page 11 of 18

Simply logging in & out of Oracle .

Using arrays to insert from a file : #include<stdio.h> EXEC SQL BEGIN DECLARE SECTION; VARCHAR uid[20]; VARCHAR pwd[20]; int empno[10]; VARCHAR ename[100] [15]; VARCHAR job[100][10]; VARCHAR hiredate[100][9]; FLOAT sal[100]; int deptno[100]; int loop; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; FILE *fp; main() { int i,fsret; strcpy(uid.arr,SCOTT); uid.len=strlen(uid.arr); strcpy(pwd.arr,TIGER); pwd.len=strlen(pwd.arr); EXEC SQL WHENEVER SQLERROR EXEC SQL CONNECT :uid :pwd; printf(Connected to Oracle user %s ,uid.arr); if(fp=fopen(test.dat,r)== NULL) { printf(error opening file test.dat \n); exit(1); } while(1) { for(i=0;i<100;i++) { fsret=fscanf(fp,%d %s %s %s %f %d, &empno[i],ename[i].arr,job[i].arr,hiredate[i].arr,&sal[i],&deptno[i]); if(fsret = = EOF) break; if(fsret = = 0) { printf(incompatible field on the line \n); exit(1); } ename[i].len=strlen(ename[i].arr);
PRO * C Page 12 of 18

GOTO ERRPT; IDENTIFIED

BY

job[i].len=strlen(hjob[i].arr); hiredate[i].len=strlen(hiredate[i].arr); } loop=i; EXEC SQL FOR :loop INSERT INTO EMP(empno,ename,job,hiredate,sal,deptno) values(:empno,:ename,:job,:hiredate,:sal,:deptno); EXEC SQL COMMIT WORK; printf(%d rows inserted \n,sqlca.sqlerrd[2]); if(loop<100) break; } printf(file test.dat loaded); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL COMMIT WORK RELEASE; exit(0); errpt: printf(\n %.70s\n,sqlca.sqlerrm.sqlerrmc); EXEC SQL ROLLBACK WORK RELEASE; exit(1); } EXAMPLE #3 This program uses dynamic SQL method to create a table insert a row,commit the insert then drop the table. #include <stdio.h> #include <string.h> #include <sqlca.h> #include <oraca.h> EXEC ORACLE OPTION (ORACA=YES); EXEC ORACLE OPTION (RELEASE_CURSOR=YES); void sql_error(); typedef char asciz[80]; EXEC SQL TYPE asciz IS STRING (80) REFERENCE; main() { char *username=SCOTT; char *password=tiger asciz sqlstmt1; char sqlstmt2[10];
PRO * C Page 13 of 18

VARCHAR sqlstmt3[80]; EXEC SQL WHENEVER SQLERROR DO sql_error(oracle error); oraca.orastxtf=ORASTFERR; EXEC SQL CONNECT :username IDENTIFIED BY :password; puts(connected to oracle); puts(create table dyn1 (col1 varchar2(4))); EXEC SQL EXECUTE IMMEDIATE CREATE TABLE dyn1 (col1 varchar2(4)); strcpy((char*) sqlstmt1,INSERT INTO dyn1 values(TEST)); puts(sqlstmt1); EXEC SQL EXECUTE IMMEDIATE :sqlstmt2; strcpy((char *) sqlstmt3.arr,DROP TABLE DYN1); sqlstmt3.len=strlen((char *) sqlstmt3.arr); puts((char *) sqlstmt3.arr); EXEC SQL EXECUTE IMMEDIATE :sqlstmt3; EXEC SQL COMMIT RELEASE; puts(have a good day); return 0; } void sql_error(msg) char *msg; { printf(\n ...*s\nsqlca.sqlerrm.sqlerrml,sqlca.sqlerrm.sqlerrmc); printf(%..*s\n, oraca.orastxt.orastxtl,oraca.orastxt.orastxtc); printf(on-line %d of %.*s ,oraca.oraslnr,oraca.orasfnm.orasfnml, oraca.orasfnm.orasfnmc); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK RELEASE; exit(1); } EXAMPLE #4 SQL*Forms User Exit This user exit concatenates form fields. To call the user exit from a SQL*forms trigger, use the syntax : user_exit(CONCAT field1,field2,.......,result_field); where user_exit is a packaged procedure supplied with SQL*forms and CONCAT is the name of the user exit. A sample form named CONCAT invokes the user exit.
PRO * C Page 14 of 18

#define min(a,b) ((a < b) ? a : b) #include <stdio.h> #include <string.h> #include <sqlca.h> EXEC SQL BEGIN DECLARE SECTION; VARCHAR field[81]; VARCHAR value[81]; VARCHAR result[241]; EXEC SQL END DECLARE SECTION; int concat(cmd,cmdlen,msg,msglen,query); char *cmd; int *cmdlen; char *msg; int *msglen; int *query; { char *cp = cmd + 7; char 8fp = (char*) &field.arr[0]; char errmsg[81]; int errlen; result.arr[0] = \0 for(; *cp != \0; cp++) { if(*cp != , && *cp != ) { *fp = *cp; fp++; } else if(*cp == ) { *fp = \0; field.len = strlen((char*) field.arr); EXEC IAF GET :field INTO :value; value.arr[value.len] = \0; strcat((char*) result.arr,(char*) value.arr); fp = (char*) &field.arr[0]; } *fp = \0; field.len = strlen((char *) field.arr); result.len = strlen((char *) result.arr); EXEC IAF PUT :field VALUES (:result);
PRO * C Page 15 of 18

RETURN(IAPSUCC); sqlerror; strcpy(errmsg, CONCAT : ); strncat(errmsg, sqlca.sqlerrm.sqlerrmc,min(72,sqlca.sqlerrm.sqlerrml)); errlen = strlen(errmsg); sqliem(errmsg, &errlen); return(IPAFAIL); EXAMPLE 5: This program connects to oracle prompts the user for department number then calls a pl/sql procedure named get_employees which is stored in package calldemo. #include <stdio.h> #include <string.h> typedef char asciz; EXEC SQL BEGIN DECLARE SECTION; EXEC SQL TYPE asciz IS STRING(20); asciz username[20]; asciz passwd [20]; int dept_no; char emp_name[10][21]; char job[10][21]; float salary[10]; int done_flag; int array_size; int num_ret; int SQLCODE; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA;

PRO * C

Page 16 of 18

QUIZ
1. 2. 3. 4. 5. The PRO*C program should be run with command ................... proc.mk file is used to ................... In PRO*C all statements must begin with......... The program needs a host variable to store the text of ................ statements . ................ structure should be included through which oracle make runtime status information.

PRO * C

Page 17 of 18

PRO * C

Page 18 of 18