Anda di halaman 1dari 22

Embedded SQL

You can embed SQL statements into many programming languages procedural power (loops, variables, etc.) The main components of embedded SQL programming:

Regular program blocks SQL code Methods to connect to the database, invoke the SQL code and retrieve results Methods to pass data from program variables to the SQL code Methods to retrieve data from the result of queries to program variables

9/16/2012

4380 Database Systems - Fall 2002

Example
#include <stdio.h> exec sql include sqlca; char user_prompt[] = "Please enter username and password: char cid_prompt[] = "Please enter customer ID: "; ";

int main() { exec sql begin declare section; char cust_id[5]; char cust_name[14]; float cust_discnt; char user_name[20], user_pwd[20]; exec sql end declare section;

/* declare SQL host variables

*/

/* host var for discnt value

*/

exec sql whenever sqlerror goto report_error; /* error trap condition exec sql whenever not found goto notfound; /* not found condition 9/16/2012 4380 Database Systems - Fall 2002

*/ */ 2

Example
exec sql connect :user_name identified by :user_pwd; /* ORACLE format: connect */

while (prompt(cid_prompt, 1, cust_id, 4) >= 0) { exec sql select cname, discnt into :cust_name, :cust_discnt /* retrieve cname, discnt */ from customers where cid = :cust_id; exec sql commit work; /* release read lock on row */ printf("CUSTOMER'S NAME IS %s AND DISCNT IS %5.1f\n", cust_name, cust_discnt); /* NOTE, (:) not used here continue; }

*/

9/16/2012

4380 Database Systems - Fall 2002

ProC
Each ESQL statement starts with EXEC SQL keyword and ends with a semicolon ; A pre-compiler will scan a program file and only read the statements enclosed within EXEC SQL statements and disregard everything else. SQLCA is a specific data structure for storing status codes of all SQL operations /* always have this for error handling*/ exec sql include sqlca ;
9/16/2012 4380 Database Systems - Fall 2002 4

Program.pc

Program.c

9/16/2012

4380 Database Systems - Fall 2002

Variables in ESQL
All variables that will be used in an SQL statement must be declared using an ESQL declaration and data type exec sql begin declare section ; VARCHAR e_name[30], username[30], passwd[30] ; INTEGER e_ssn, e_dept_id ; exec sql end declare section ; You can use almost any SQL command in ESQL as long as proper input to these commands are provided in the form of program variables. To execute any command, you must first connect to a database in which all your tables reside. exec sql connect :username identified by :passwd ;

9/16/2012

4380 Database Systems - Fall 2002

Executing SQL commands


Suppose we want to find the name of an employee given his/her SSN (input by the user of the program): exec sql select name, dept_id into :e_name, :e_dept_id from employee Program variables are where ssn = :e_ssn ; preceded by :
Read the value of the variable e_ssn and execute the SQL statement using this value, store the returned values of columns name and dept_id in the program variables e_name and e_dept_id. Compare the above query with the expression below. What is the difference? exec sql select name, dept_id from employee where ssn = e_ssn ;
9/16/2012 4380 Database Systems - Fall 2002 7

Dealing with Strings


There is a mismatch between the definition of a string in Oracle and in C/C++.

In C, the end of a string is identified by the null character \0. Hence, Sibel would be stored as characters S,i,b,e,l,\0. In Oracle, the length of a string is stored together with the string and there is no special end of string character. If you convert a data string from Oracle to C, you must pad it with \0 manually!

The data type VARCHAR e_name[30] is translated by the precompiler to the following structure:
struct { unsigned short len unsigned char arr[30] } e_name ;
9/16/2012 4380 Database Systems - Fall 2002 8

More on strings
Putting the pieces together: strcpy(username.arr, Sibel Adali) ; username.len = strlen(Sibel Adali) ; strcpy(passwd.arr, tweety-bird) ; passwd.len = strlen(tweety-bird) ; exec sql connect :username identified by :passwd ; scanf(%d, &e_ssn) ; exec sql select name, dept_id into :e_name, :e_dept_id from employee where ssn = :e_ssn ; e_name.arr[e_name.len] = \0 ; /* so can use string in C*/ printf(%s, e_name.arr) ; exec sql commit work ; /* make any changes permanent */ exec sql disconnect ; /* disconnect from the database */
9/16/2012 4380 Database Systems - Fall 2002 9

ESQL - Cursors
When a select statement returns a set of tuples, then the tuples (rows) can only be retrieved one by one. programming language variables can contain only one value at a time this is sometimes called an impedance mismatch Cursor operations declare a cursor using a regular SQL query (no into). exec sql declare emps_dept cursor for select ssn, name from employee where dept_id = :e_dept_id ;

9/16/2012

4380 Database Systems - Fall 2002

10

ESQL More Cursors


More cursor operations open a cursor: means the corresponding SQL query is executed, the results are written to a file (or a data structure) and the cursor is pointing to the first row. exec sql open emps_dept ;

read the current row pointed to by the cursor using fetch. At the end of fetch, the cursor is moved to point to the next tuple. exec sql fetch emps_dept into :e_ssn, :e_name ;

9/16/2012

4380 Database Systems - Fall 2002

11

How do we know when we reach the end of a cursor?


Each SQL statement executed in a program produces a status code that can be retrieved from the SQL Communication Area (SQLCA) variables. Check the sqlcode to see if the end of a cursor is reached (its expected value depends on the system). if (sqlca.sqlcode == -1) { } Error handling statements exec sql whenever sqlerror {continue, stop, goto label, call function} exec sql whenever is a trap condition, it hold for all exec sql statements unless a new trap condition overrides the current one.
9/16/2012 4380 Database Systems - Fall 2002 12

Cursors and snapshots


If a cursor is declared as INSENSITIVE, the contents of the cursor is computed once when the cursor is opened, and remains the same until the cursor is closed, even if the underlying data tables change during the this time. DECLARE CURSOR cursor-name INSENSITIVE CURSOR FOR table-expression This type of cursor is a snapshot of the database, a view of it at a specific time.

9/16/2012

4380 Database Systems - Fall 2002

13

Cursors for update


If a cursor is declared for update, then updates can be performed on the current tuple.
DECLARE CURSOR cursor-name CURSOR FOR table-expression FOR UPDATE OF column-list UPDATE table-name SET assignment-list WHERE CURRENT OF cursor-name DELETE FROM table-name WHERE CURRENT OF cursor-name

For these updates to have an effect, the cursor must not be INSENSITIVE.
9/16/2012 4380 Database Systems - Fall 2002 14

Constraints
When constraints are violated, they cause an exception (or sqlerror) to be thrown. When are constraints violated?

If constraint checking for a constraint is immediate, as soon as an SQL statement causes the constraint to become false, it is rolled back. If a constraint is defined to be deferrable, then the constraint is not checked until a transaction tries to commit. Then, if it is violated, the whole transaction is rolled back.
CONSTRAINT name CHECK DEFERRABLE
4380 Database Systems - Fall 2002 15

9/16/2012

Transactions
The most common ESQL statements are SELECT, INSERT INTO, and UPDATE statements. A transaction in a program starts with the first read or write to a database (not with connect) and ends when either one of the following commands is executed exec sql commit work ; /* changes to the database are made permanent */ exec sql rollback work ; /* restore all tuples to their original values */ If a program did not complete correctly, then changes can be undone to restore a consistent state.

9/16/2012

4380 Database Systems - Fall 2002

16

Dynamic SQL
In Dynamic SQL, embedded SQL statements are created on the fly using strings! these strings are fed to an exec sql statement exec sql execute immediate :sql_string Since dynamic SQL statements are not known to the pre-compiler at compile time, they must be optimized at run time! Create a query once using a prepare statement and run it multiple times using the execute statement. strcopy(sqltext.arr, delete from employee where ssn = ?) ; sqltext.len=str.len(sqltext.arr) ; exec sql prepare del_emp from :sqltext ; exec sql execute del_emp using :cust_id ;
9/16/2012 4380 Database Systems - Fall 2002 17

SQLDA
When we execute a dynamic SQL statement, we do not know which columns will be returned and how many columns will be returned. The SQLDA descriptor definition allows us to find the number of columns and the value for each column. exec sql include sqlda ; exec sql declare sel_curs cursor for sel_emps ; exec sql prepare sel_emps from :sqltext ; exec sql describe sel_emps into sqlda ; exec sql open sel_curs ; exec sql fetch sel_curs using descriptor sqlda ;
9/16/2012 4380 Database Systems - Fall 2002 18

JDBC
Driver is a piece of software that enables communication between a program and a database system (DMBS specific packages). It implements a number of main classes:

Connection (opening, closing, committing) Statement (executing queries) Result set (going through cursors, extracting information)

9/16/2012

4380 Database Systems - Fall 2002

19

JDBC
import java.sql.*; import oracle.sql.*; import oracle.jdbc.driver.*; class Employee { public static void main (String args []) throws SQLException {//Set your user name and the password String userName = "dummy" ; String passWord = "dummy" ; // Load the Oracle JDBC driver DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@acadoracle.server.rpi.edu:1521:ora9", userName,passWord);
9/16/2012 4380 Database Systems - Fall 2002 20

JDBC
// Create a statement which will return a cursor that // will allow you to scroll the result set using both // "next" and "previous" methods try { Statement stmt = conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

ResultSet rset = stmt.executeQuery ("SELECT name, oid FROM items ");

9/16/2012

4380 Database Systems - Fall 2002

21

JDBC
// Iterate through the result and print the item names while (rset.next ()) { //Get item name, which is the first column System.out.println (rset.getString (1)); PreparedStatement pstmt = conn.prepareStatement ("SELECT name FROM owners WHERE oid = ?") ; //Feed the owner id retrieved from rset into pstmt pstmt.setInt(1, rset.getInt (2)); ResultSet dset = pstmt.executeQuery() ; if (dset.next()) System.out.println(dset.getString (1)); } } } catch (SQLException) { error-handling-code } } }
9/16/2012 4380 Database Systems - Fall 2002 22

Anda mungkin juga menyukai