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 statement SQL statement C statement C statement SQL statement … File extensions: .ps (Oracle) .sc. (Ingres) Embedded program SQL Precompiler SQL C functions Ingres: esqlc. esqlc program.sc program.c Oracle: proc. proc program.sc program.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 Server Procedures SQL statement SQL statement execution C variables accept the answer 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 : cod cname color weight integer char(15) char(15) float struct { long cod; char cname[16]; char color[16]; double weight; } 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 CURSOR DECLARE knev INSENSITIVE 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.sqlerrm structure 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?