To Chapter 4.12
Embedded SQL
Written by T. Nikovits and A. B. Novak
Why:
there are some problems which can not be expressed in SQL (eg. loops)
riport generation
graphical interface
Solution:
-embedded SQL
- 4GL developer tools
(Oracle Developer)
EXEC <SQL statements> (END-EXEC)
Declarations: variables for both languages (for the SQL and for the host languagae)
EXEC SQL BEGIN DECLARE SECTION;
…..
EXEC SQL END DECLARE SECTION;
Host: C
C statementSQL statement
C statement
C statement
SQL statement
…
File extensions: .ps (Oracle) .sc. (Ingres)
Embedded program SQL Precompiler SQL C functions
Ingres: esqlc.
esqlc program.scprogram.c
Oracle: proc.
proc program.scprogram.c
The result is a C program CompileRun
You have to attached the libraries. These can be found in the DBMS, they are installed already with the DBMS
Environment
Client / ServerProcedures
SQL statement / SQL statement
execution
C variables / Answer
accept the answer
Other procedures for evaluation of answer
- The SQL statement are sent to the server
- Answer:
- error message (depending of the success of a delete, update)
- query result (Select…)
Syntax
Sql statements should be recognized, the precompiler compiles only these ones.
General syntax:
EXEC SQL <SQL statement > ;
Example:
EXEC SQL
CREATE TABLE ITEM
(COD NUMBER(5), INAME VARCHAR2(15)) ;
EXEC SQL
DELETE FROM ITEM
WHERE INAME IN
('TABLE', 'MONITOR', 'PENCIL') ;
EXEC SQL
INSERT INTO ITEM(COD, CNAME)
VALUES (10, 'Keyboard') ;
Anywhere can be an SQL statement or a C statement.
Variables
In SQL - statements instead of using database items we can use C variables. They could be simple variables, structures, or pointers.
EXEC SQL DELETE FROM ITEM
WHERE CNAME = <C variable> ;
EXEC SQL INSERT INTO ITEM(COD, CNAME)
VALUES <C variable> ;
Variables must be declared in the declare session:
EXEC SQL BEGIN DECLARE SECTION ;
variable declaration by C syntax
EXEC SQL END DECLARE SECTION ;
Example:
EXEC SQL BEGIN DECLARE SECTION ;
long newcod;
char cname[16];
EXEC SQL END DECLARE SECTION ;
C variables should be written AFTER : . In this way they can be distinguished from the database items (sharing same name, eg. Attribute names)
Example:
EXEC SQL INSERT INTO ITEM(cod)
VALUES :newcod ;
EXEC SQL DELETE FROM ITEM
WHERE cname = :cname ;
What would happen if we forgot to put : there?
Question:
What is the result of the following program?
EXEC SQL
SELECT DNAME, DEPTNO, MANAGER, BUDGET, ADDRESS, PHONE
INTO :dname, :deptno, :manager, :budget, :address, :phone
FROM DEPT
WHERE DNAME= "research";
Using structures
TABLE ITEM :
codinteger
cnamechar(15)
colorchar(15)
weightfloat
struct {
longcod;
charcname[16];
charcolor[16];
doubleweight;
} item_rec;
Referring to a strucuture in SQL:
EXEC SQL INSERT INTO ITEM
VALUES (:item_rec) ;
Or:
EXEC SQL INSERT INTO ITEM
VALUES (:item_rec.cod, :item_rec.cname,
:item_rec.color, :item_rec.weight) ;
Connect to database
Syntax:
EXEC SQL CONNECT : user_name
IDENTIFIED BY : password ;
Disconnect syntax:
EXEC SQL DISCONNECT ;
Remark:
- Oracle: COMMIT RELEASE
ROLLBACK RELEASE
- Ingres: multisession (SESSION)
Cursors
Cursors are useful to get back one row from the result of a SELECT statement.
SELECT CURSOR pointing to the actual tuple
Creating a cursor:
EXEC SQL DECLARE cname CURSOR
FOR SELECT ... ;
This reflects changes.
EXEC SQL DECLARE knev INSENSITIVE CURSOR
FOR SELECT ... ;
Cursor can be defined only with SELECT grant
Examples:
1.
EXEC SQL
DECLARE DEPT-EMP CURSOR FOR
SELECT dname, surname, first_name
FROM DEPT d, EMP e
WHERE emp.deptno = emp.deptno
ORDER BY deptno, surname, first_name;
2. AVG salaries for each dept:
EXEC SQL
DECLARE dept-avg-sal CURSOR FOR
SELECT dnaem, AVG(sal)
FROM DEPT d, EMP e
WHERE d.deptno = e.deptno.
GROUP BY deptno
ORDER BY dname;
Using the cursor first we have to open it::
EXEC SQL OPEN cursor_name ;
(at runtime it will point to the tuple used latest by the program, delete, update, insert)
Read and go to next:
EXEC SQL FETCH cursor_name
INTO <C variables> ;
The tuple, to that the cursor points will be read into C variables. TYPE CONVERSION!!!
Closing cursor:
EXEC SQL CLOSE curso_name ;
Remark:
cursor_name is NOT a C-variable, that is why : is not needed.
Updating data using cursors
The type of update must be declraed in the cursor definition:
EXEC SQL DECLARE cursor_name CURSOR FOR SELECT ....
FOR UPDATE [OF column1, column2, ...] ;
Remark:
Only for ONE table used by select. No distinct, no group by, no having, no union!!
Syntax:
EXEC SQL UPDATE <table_name>
SET column = <statement>, ...
WHERE CURRENT OF <cursor_name> ;
Deleting rows:
EXEC SQL DELETE FROM <table_name>
WHERE CURRENT OF <cursor_name> ;
Error handling
For each SQL statement the system feeds back to the client program whether the statement execution was successful or not. That means, that the server program set the values of certain variables of the client program.
The program is responsible for defining these variables:
EXEC SQL INCLUDE SQLCA;
This is a structure type C variables, Named: SQLCA.
Main elements:
sqlca.sqlcode: long sqlcode;
error code for last SQL statement:
= 0 succesfully executed
< 0 error
> 0 exceptional case, like no rows in the answer = 100, or end table)
sqlca.sqlerrmstructure type: lenght of error message and first 70 characters
NULL values handling - indicator variables
INTERBASE SQL TUTORIAL:The following program declares a cursor, opens the cursor, and then loops through the cursor’s active set, fetching and printing values. The program closes the cursor when all processing is finished or an error occurs.
#include <stdio.h>
EXEC SQL
BEGIN DECLARE SECTION;
char deptname[26];
char lname[16];
char fname[11];
EXEC SQL
END DECLARE SECTION;
main ()
{
EXEC SQL
WHENEVER SQLERROR GO TO abend;
EXEC SQL
DECLARE DEPT_EMP CURSOR FOR
SELECT DEPARTMENT, LAST_NAME, FIRST_NAME
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.DEPT_NO = E.DEPT_NO"
ORDER BY DEPARTMENT, LAST_NAME, FIRST_NAME;
EXEC SQL
OPEN DEPT_EMP;
EXEC SQL
FETCH DEPT_EMP
INTO :deptname, :lname, :fname;
while (!SQLCODE)
{
printf("%s %s works in the %s department.\n",fname,
lname, deptname);
EXEC SQL
FETCH DEPT_EMP
INTO :deptname, :lname, :fname;
}
EXEC SQL
CLOSE DEPT_EMP;
exit();
abend:
if (SQLCODE)
{
isc_print_sqlerror();
EXEC SQL
ROLLBACK;
EXEC SQL
CLOSE_DEPT_EMP;
EXEC SQL
DISCONNECT ALL;
exit(1)
}
else
{
EXEC SQL
COMMIT;
EXEC SQL
DISCONNECT ALL;
exit()
}
}
Questions to review:
1. Explain each unit briefly.
2. Insert a variable named as number_of tuples, type INTEGER, whose value is equal to the number of rows printed in the program.
3. List the variables in the host language (C)
4. How many cursors are defined in this program.
5. Give the names of the cursors.
6. What will be printed out if Xian Xi’s name, which is the last in the table, will be changed to Xian Xu. Why? Could you alter this result?
7. Is the transaction committed? Explain.
8. Mr. Cody has been granted for selection on all tables. Could he run that program?