1. SQL
1
Fall 2001 Database Systems 1
Scalar subqueries
• A scalar subquery is any expression that produces a
single value (single tuple/ single column)
• Examples:
SELECT max(amount) FROM bids
SELECT count(*) FROM items
• Scalar subqueries can be used as if they were
“constants”
– in expressions in the WHERE clause, and
– to output values in the SELECT clause
Fall 2001 Database Systems 2
Scalar subqueries
• Find items with average bid 60 or more. Print the
name of the item and the average bid.
SELECT I.name, avg(B.amount)
FROM Items I, Bids B
WHERE I.iid=B.iid
GROUP BY I.iid, I.name
HAVING avg(B.amount) > 60
2. SQL
2
Fall 2001 Database Systems 3
Scalar subqueries
• Find items with average bid 60 or more. Print the name
of the item and the average bid.
SELECT I.name,
FROM Items I
WHERE 60 < (SELECT avg(B.amount)
FROM bids B
WHERE B.iid = I.iid)
(SELECT avg(B2.amount)
FROM Bids B2
WHERE B2.iid = I.iid) avgAmount
Return a single
value for each tuple
Check the boolean condition
for each tuple
Fall 2001 Database Systems 4
What can’t you do with SQL
or can you?
• You are limited by the functions implemented in the
database
– Not allowed: SELECT median(salary) …
– You can add new functions to the database engine and
implement new types in a native programming language like
C,C++ (support varies)
• You can have subselects in FROM and WHERE that
return a set of values, but not in SELECT
– Allowed: SELECT * FROM (SELECT b.bid FROM bids b
WHERE b.amount>20)
– Not allowed: SELECT avg(SELECT b.amount FROM .. ) FROM
..
3. SQL
3
Fall 2001 Database Systems 5
What can’t you do with SQL
or can you?
• You cannot ask transitive queries
– Given a relation “emp(A,B)” for immediate managers B or A, you cannot
find all managers of a person A.
– SQL3 includes a recursive query definition construct –not implemented
in Oracle.
WITH RECURSIVE manages(emp, mgr) AS
(SELECT E1.emp, E1.mgr FROM employee E1)
UNION
(SELECT M.emp, E2.mgr FROM manages M, employee E2
WHERE M.mgr = E.id)
SELECT M2.emp
FROM manages M2
WHERE M2.emp = M2.mgr ;
Recursive queries may produce infinite loops and it is best left to programmers
with solid logic background.
Fall 2001 Database Systems 6
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
4. SQL
4
Fall 2001 Database Systems 7
#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; /* declare SQL host variables */
char cust_id[5];
char cust_name[14];
float cust_discnt; /* host var for discnt value */
char user_name[20], user_pwd[20];
exec sql end declare section;
exec sql whenever sqlerror goto report_error; /* error trap condition */
exec sql whenever not found goto notfound; /* not found condition */
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.1fn",
cust_name, cust_discnt); /* NOTE, (:) not used here */
continue;
Fall 2001 Database Systems 8
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 ;
5. SQL
5
Fall 2001 Database Systems 9
Program.pc
Program.c
Fall 2001 Database Systems 10
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 ;
6. SQL
6
Fall 2001 Database Systems 11
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
where ssn = :e_ssn ;
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 ;
Program variables are
preceded by “:”
Fall 2001 Database Systems 12
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 pre-
compiler to the following structure:
struct {
unsigned short len
unsigned char arr[30]
} e_name ;
7. SQL
7
Fall 2001 Database Systems 13
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 */
Fall 2001 Database Systems 14
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 ;
8. SQL
8
Fall 2001 Database Systems 15
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 ;
Fall 2001 Database Systems 16
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. SQL
9
Fall 2001 Database Systems 17
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.
Fall 2001 Database Systems 18
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 ;
10. SQL
10
Fall 2001 Database Systems 19
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 ;
Fall 2001 Database Systems 20
JDBC – Dynamic SQL
• 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)
11. SQL
11
Fall 2001 Database Systems 21
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:@vcmr-57.server.rpi.edu:1521:ora8",
userName,passWord);
Fall 2001 Database Systems 22
// Create a statement which will return a cursor that will allow
you to
// scroll the result set using both "next" and "previous"
methods
Statement stmt = conn.createStatement
(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet rset = stmt.executeQuery
("SELECT name, oid FROM items ");
// 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));
} } }