========================================================================= An Introduction/Guide on How to Program in C with Embedded SQL Statements ========================================================================= (The follow sample program is stored as sample.sc. You can type 'make' to compile it. This should be a good starting point for you to write your embedded sql codes.) Step 1: Writing embedded SQL code in C programs To write C-code which manipulates the database, there are a few special steps that are needed to be taken to ensure your program communicating with INGRES System smoothly. The following program will serve as an example: Sample program: #include <stdio.h> (1) EXEC SQL BEGIN DECLARE SECTION; int status; char s_num[6]; char sname[20]; EXEC SQL END DECLARE SECTION; (2) EXEC SQL INCLUDE SQLCA; (3) EXEC SQL WHENEVER SQLERROR GOTO Stmt_Err; (4) /* ** Procedure : Print_Error ** Purpose : SQLCA error detected. Retrieve the error message and ** print it. ** Parameters: None ** */ #define ERROR_BUFFER 150 void Print_Error() { EXEC SQL BEGIN DECLARE SECTION; char error_buf[ERROR_BUFFER]; /* For error text retrieval */ EXEC SQL END DECLARE SECTION; EXEC SQL INQUIRE_SQL (:error_buf = ERRORTEXT); printf("\nSQL Error:\n %s\n",error_buf); } /*Print_Error */ main() { (5) EXEC SQL CONNECT testdb; scanf("%d", &status); (6) EXEC SQL UPDATE S SET sname = 'wan' WHERE status = :status; (7) EXEC SQL DECLARE C1 CURSOR FOR SELECT SNAME, STATUS FROM S WHERE s# > '50544'; (8) EXEC SQL OPEN C1; (9) EXEC SQL WHENEVER NOT FOUND GOTO Label; for (;;) { printf("Fetching : "); (10) EXEC SQL FETCH C1 INTO :sname, :i_status; printf("name : %s\n", sname); } Label: (11) EXEC SQL CLOSE C1; (12) EXEC SQL DISCONNECT ; exit(0); Stmt_Err: EXEC SQL WHENEVER SQLERROR CONTINUE; Print_Error(); } The basic structure of the program is the same as a standard C program, but in order to communicate with INGRES a few extra commands need to be introduced: (1) Declaration section Declaring all variables that will be used to communicate with the SQL statements, e.g. to hold the tuple values from a selection; to specify parameter for a query/update; to store values to be inserted etc. Each type in INGRES relation's attribute should correspond nicely to a specific data type of C, except date, which should probably be converted into character strings. The syntax of the declaration section should be: EXEC SQL BEGIN DECLARE SECTION; <declarations> EXEC SQL END DECLARE SECTION; (2) EXEC SQL INCLUDE SQLCA; This statement tells the program to include SQLCA, the structure that hold the error and status information returned by INGRES. This statement should always be included. (3) EXEC SQL WHENEVER SQLERROR <action>; This statement tell the program what to do when an error occurs while trying to execute a SQL command, where <action> can be stop -- to stop execution of program. GOTO <label> -- will call a branch to the <label> where execution of the program will continue. (4) A standard SQL Error Detection Procedure. This procedure is called when a SQL error occurs. It prints out the appropriate informations about the error so that you can modify your program easily. (5) EXEC SQL CONNECT <database name>; This command connects the program to the database you just created. Note the database name is case sensitive. (6) UPDATE, INSERT or DELETE These commands can be written simply as their SQL syntaxs, with EXEC SQL added in the front: EXEC SQL UPDATE S SET sname = 'WAN' WHERE status = :status; If program variables need to be used in the SQL statements, they must be preceded by a colon (e.g. :status), and of course they must have been declared in the declaration section. (7) - (11) Execute a database query There are a few steps needed to execute a database query: Firstly, a CURSOR needed to be set up. A cursor is an area reserved in memory where the tuples retrieved from a query are stored. The tuples selected will be stored in the cursor and then fetched to the program one tuple at a time. To declare a cursor, use the DECLARE statement: EXEC SQL DECLARE <cursor name> CURSOR FOR <select_statement> ; Once again, if program variables need to be used, they must be preceded by a colon (eg :status). Next the cursor needs to be opened by the OPEN statement, EXEC SQL OPEN <cursor name>; Note that there may be a upper limit to the number of cursor allowed to be opened. So after finished using a cursor, it is always good practice to close it: EXEC SQL CLOSE <cursor name>; Now, the cursor has been opened, the next thing you need to do is to tell the program what to do when all the matched tuples has been read: EXEC SQL WHENEVER NOT FOUND GOTO <label>; This statement tells the program what to do when there is no more tuples to fetch. After all the above declaration, it is now ready to fetch the tuples. The command for fetching a tuple is: EXEC SQL FETCH <cursor name> INTO <program variable list>; The list of the program variables must match the number of attributes being selected, as well as the types. Once again, a colon is needed to be attached to the beginning of each variable. Normally the user wants to execute a select command, and process each tuple in some manner. A for-loop, such as one above, keep fetching the tuples until all have been fetched, and then branched to the label 'label' (thus exiting the loop), is a good idea. However, be careful: the loop will terminate only at the FETCH statement when there is no more tuples to fetch. Thus in the example, if 5 tuples is fetched by the select statement, "Fetching : " will be printed 6 (not 5) times. (12) Closing a database EXEC SQL DISCONNECT ; This statement will disconnect(close) the database. ------------ Step 2: Compiling and running the C program a) : All files with the programs should be with suffix .sc b) : After a program have been written, issue the command > esqlc <filename>.sc A <filename>.c file will appear. "esqlc" is the command of the Embedded SQL Preprocessor. c) : Compile the .c file with this command >cc -o <output filename> <filename>.c /usr/kits/sql/ingres/lib/libsql.a -lm The extra stuff at the end is to ensure all the relevant procedures are linked to the program. Also you may experience in some cases that the compilation will fail because of "file size exceeded". You can change the file size limit by >limit filesize 1000 (or some other number, 1000 should be OK) If you know how to use the makefile, you can write down your own makefile following the example: # INGRES.PLUS makefile CC = cc SCC = esqlc LIBS = $(II_SYSTEM)/sql/lib/libsql.a \ /usr/lib/libm.a \ /usr/lib/libc.a OBJ= test.o test: $(OBJ) $(CC) -o test $(OBJ) -ll $(LIBS) test.o: test.c $(CC) -c -g test.c test.c: test.sc $(SCC) test.sc d) :After preprocessing and compiling your C program with Embedded SQL Statements, you may run your program now. -------------
© William Yuan 2000
Email William