m3.pdf Dbms
m3.pdf Dbms
Semester: 05 Credits: 04
Number of Hours/Week: 03:02:0 IA Marks: 40
Total Number of Hours: 50 Exam Marks: 60
Module-III Notes
TOPICS
from applications
In general, each individual NULL value is considered to be different from every other NULL
value in the various database records.
When a NULL is involved in a comparison operation, the result is considered to be
UNKNOWN (it may be TRUE or it may be FALSE). Hence, SQL uses a three-valued logic with
values TRUE, FALSE, and UNKNOWN instead of the standard two-valued (Boolean) logic with
values TRUE or FALSE. It is therefore necessary to define theresults (or truth values) of three-
when the logical connectives AND, OR, and NOT are used. Table 8.1 shows the resulting values.
valued logical expressions.
• The first nested query selects the project numbers of projects that have an employee with last
name ‘Smith’ involved as manager, while the second nested query selects the project
numbers of projects that have an employee with last name ‘Smith’ involved as worker. In the
outer query, use the OR logical connective to retrieve a PROJECT tuple if the PNUMBER
value of that tuple is in the result of either nested query.
• Make a list of all project numbers for projects that involve an employee whose last name is
‘Smith’, either as a worker or as a manager of the department that controls the project.
• If a nested query returns a single attribute and a single tuple, the query result will be a single
(scalar) value. In such cases, it is permissible to use = instead of IN for the comparison
operator. In general, the nested query will return a table (relation), which is a set or multiset
of tuples.
• SQL allows the use of tuples of values in comparisons by placing them within parentheses.
To illustrate this, consider the following query:
• Select the Essns of all employees who work the same (project, hours) combination on some
project that employee ‘John Smith’ (whose Ssn = ‘123456789’) works on.
SELECT DISTINCT Essn
FROM WORKS_ON
WHERE (Pno, Hours) IN ( SELECT Pno, Hours
FROM WORKS_ON
WHERE Essn=‘123456789’);
• In this example, the IN operator compares the subtuple of values in parentheses (Pno, Hours)
within each tuple in WORKS_ON with the set of type-compatible tuples produced by the
nested query.
• In addition to the IN operator, a number of other comparison operators can be used to
compare a single value v (typically an attribute name) to a set or multiset V (typically a
nested query).
• The = ANY (or = SOME) operator returns TRUE if the value v is equal to some value in the
set V and is hence equivalent to IN. The two keywords ANY and SOME have the same
effect.
Dept. of ISE, RNSIT Page 4
• Other operators that can be combined with ANY (or SOME) include >, >=, <, <=, and <>.
• The keyword ALL can also be combined with each of these operators. For example, the
comparison condition (v > ALL V) returns TRUE if the value v is greater than all the values
in the set (or multiset) V.
• Example: Retrieve the names of employees whose salary is greater than the salary of all the
employees in department 5:
SELECT Lname, Fname
FROM EMPLOYEE
WHERE Salary > ALL ( SELECT Salary
FROM EMPLOYEE
WHERE Dno=5 );
• Notice that this query can also be specified using the MAX aggregate function (discussed
later).
• In general, there are several levels of nested queries. Ambiguity among attribute names exist
if attributes have the same name—one in a relation in the FROM clause of the outer query,
and another in a relation in the FROM clause of the nested query. The rule is that a reference
to an unqualified attribute refers to the relation declared in the innermost nested query.
• For example, in the SELECT clause and WHERE clause of the first nested query of Q4A, a
reference to any unqualified attribute of the PROJECT relation refers to the PROJECT
relation specified in the FROM clause of the nested query. To refer to an attribute of the
PROJECT relation specified in the outer query, specify and refer to an alias (tuple variable)
for that relation.
NOT EXISTS:
• NOT EXISTS(Q) returns TRUE if there are no tuples in the result of nested query Q, and it
returns FALSE otherwise.
• Query 26. For each project on which more than two employees work, retrieve the project
number, the project name, and the number of employees who work on the project.
Dept. of ISE, RNSIT Page 17
Q26: SELECT Pnumber, Pname, COUNT (*)
FROM PROJECT, WORKS_ON
WHERE Pnumber=Pno
GROUP BY Pnumber, Pname
HAVING COUNT (*) > 2;
• Notice that while selection conditions in the WHERE clause limit the tuples to which
functions are applied, the HAVING clause serves to choose whole groups. Figure 8.6(b)
illustrates the use of HAVING and displays the result of Q26.
• Query 27. For each project, retrieve the project number, the project name, and the number of
employees from department 5 who work on the project.
Q27: SELECT Pnumber, Pname, COUNT (*)
FROM PROJECT, WORKS_ON, EMPLOYEE
WHERE Pnumber=Pno AND Ssn=Essn AND Dno=5
GROUP BY Pnumber, Pname;
• To count the total number of employees whose salaries exceed $40,000 in each department,
but only for departments where more than five employees work.
• Here, the condition (SALARY > 40000) applies only to the COUNT function in the SELECT
clause. The following shows a incorrect query:
SELECT Dname, COUNT (*)
FROM DEPARTMENT, EMPLOYEE
WHERE Dnumber=Dno AND Salary>40000
GROUP BY Dname
HAVING COUNT (*) > 5;
• This is incorrect because it will select only departments that have more than five employees
who each earn more than $40,000. The rule is that the WHERE clause is executed first, to
select individual tuples or joined tuples; the HAVING clause is applied later, to select
individual groups of tuples. Hence, the tuples are already restricted to employees who earn
more than $40,000 before the function in the HAVING clause is applied.
• One way to write this query correctly is to use a nested query, as shown in Query 28.
• Query 28. For each department that has more than five employees, retrieve the department
number and the number of its employees who are making more than $40,000.
Q28: SELECT Dnumber, COUNT (*)
Dept. of ISE, RNSIT Page 18
FROM DEPARTMENT, EMPLOYEE
WHERE Dnumber=Dno AND Salary>40000 AND
Dno IN( SELECT Dno
FROM EMPLOYEE
GROUP BY Dno
HAVING COUNT (*) > 5)
Embedding SQL commands in a host language program is straightforward. SQL statements (i.e.,
not declarations) can be used wherever a statement in the host language is allowed (with a few
restrictions). SQL statements must be clearly marked so that a preprocessor can deal with them
before invoking the compiler for the host language. Also, any host language variables used to
pass arguments into an SQL command must be declared in SQL.
In particular, some special host language variables must be declared in SQL There are,
however, two complications to bear in mind.
First, the data types recognized by SQL may not be recognized by the host language and
vice versa. This mismatch is typically addressed by casting data values appropriately before
passing them to or frorn SQL commands
The second complication h~s to do with SQL being set-oriented,
and is addressed using cursors
SQL statements can refer to variables defined in the host program. Such hos tlanguage
variables must be prefixed by a colon (:) in SQL statements and be
declared between the commands EXEC SQL BEGIN DECLARE SECTION and EXEC
SQL END DECLARE SECTION.
The declarations are similar to how they would look in a C program and, as usual in C.
are separated by semicolons
For example. we can declare variables c-sname, c_sid, c_mt'ing, and cage (with the
initial c used as a naming convention to emphasize that these are host language
variables) as follows:
The SQL-92 standard defines such a correspondence between the host language types and
SQL types for a number of host languages. In our example, c_snamc has the type
CHARACTER(20) when referred to in an SQL statement, csid has the type INTEGER, crating
has the type SMALLINT, and cage has the type REAL.
We also need some way for SQL to report what went wrong if an error condition arises when
executing an SQL statement. The SQL-92 standard recognizes two special variables for reporting
errors, SQLCODE and SQLSTATE.
SQLCODE is the older of the two and is defined to return some negative value when an error
condition arises, without specifying further just what error a particular negative integer denotes.
Example: the following Embedded'SQL statement inserts a row, whose column values me based
on the values of the host language variables contained in it, into the Sailors relation:
EXEC SQL
INSERT INTO Sailors VALUES (:c_sname, :csid, :crating, :cage);
Observe that a semicolon terminates the command, as per the convention for
terminating statements in C.
6.1.2 Cursors
A major problem in embedding SQL statements in a host language like C is that an impedance
mismatch occurs because SQL operates on set" of records, whereas languages like C do not
cleanly support a set-of-records abstraction. The solution is to essentially provide a mechanism
that allows us to retrieve rows one at a time from a relation. This mechanism is called a cursor.
We can declare a cursor on any relation or on any SQL query (because every query returns a set
of rows). Once a it is declared, we can open it (which positions the cursor just before the
first row); fetch the next row; move the cursor (to the next row, to the row after the next n, to the
first row, or to the previous row, etc., by specifying additional parameters for the FETCH
command); or close the cursor. Thus, a cursor essentially allows us to retrieve the rows in a table
by positioning the cursor at a particular row and reading its contents.
Cursors enable us to examine, in the host language program, a collection of JWS computed by
an Embedded SQL statement: usually need to open a cursor if the embedded statement is a
SELECT (i.e.) a query). However, we can avoid opening a cursor if the answer contains a single
row, as we see shortly.
As an example, we can find the name and age of a sailor, specified by assigning
a value to the host variable c_sid, declared earlier, as follows:
The INTO clause allows us to assign the columns of the single answer row to the host variables
csname and c_age. Therefore, we do not need a cursor to embed this query in a host language
program.
the following query, which computes the names and ages of all sailors with a rating greater than
the current value of the host variable cminmting
This query returns a collection of rows, not just one row. 'When executed interactively, the
answers are printed on the screen. If we embed this query in a C program by prefixing the
cOlnmand with EXEC SQL, how can the answers be bound to host language variables? The
INTO clause is inadequate because we must deal with several rows. The solution is to use a
cursor:
A cursor can be declared to be a read-only cursor (FOR READ ONLY) or, if it is a cursor on a
base relation or an updatable view, to be an updatable cursor (FOR UPDATE). If it is IIpdatable,
simple variants of the UPDATE and DELETE commands allow us to update or delete the row on
which the cursor is positioned. For example, if sinfa is an updatable cursor and open, we can
execute the following statement:
UPDATE Sailors S
SET S.rating = S.rating ~ 1
This Embedded SQL statement modifies the rating value of the row currently
pointed to by cursor sinfa; similarly, we can delete this row by executing the
next statement:
DELETE Sailors S
WHERE CURRENT of sinfo;
We illustrate the two main commands, PREPARE and EXECUTE, through a simple example:
char c_sqlstring[] = {"DELETE FROM Sailors WHERE rating>5"};
EXEC SQL PREPARE readytogo FROM :csqlstring;
EXEC SQL EXECUTE readytogo;
The first statement declares the C variable c_sqlstring and initializes its value to
the string representation of an SQL command.
The second statement results in this string being parsed and compiled as an SQL command, with
the resulting executable bound to the SQL variable readytogo. (Since readytogo is an SQL
variable, just like a cursor name, it is not prefixed by a colon.)
Embedded SQL enables the integration of SQL with a general-purpose programming language.
The details of translation vary across DBMSs, and therefore even though the source code can be
compiled to work with different DBMSs, the final executable works only with one specific
DBMS. ODBC and JDBC, short for Open DataBase Connectivity and Java DataBase
Connectivity, also enable the integration of SQL with a general-purpose programming language.
Both ODBC and JDBC expose database capabilities in a standardized way to the
application programmer through an application programming interface (API). In contrast to
Embedded SQL, ODBC and JDBC allow a single executable to access different DBMSs
'Without recompilation. Thus, while Embedded SQL is DBMS-independent only at the source
code level, applications using ODBC or JDBC are DBMS-independent at the source code level
and at the level of the executable. In addition, using ODBC or JDBC, an application can access
not just one DBMS but several different ones simultaneously.
ODBC and JDBC achieve portability at the level of the executable by introducing an extra level
of indirection. All direct interaction with a specific DBMS happens through a DBMS-specific
driver. A driver is a software program that translates the ODBC or JDBC calls into DBMS-
specific calls.
Drivers are loaded dynamically on demand since the DBMSs the application is going to access
are known only at run-time. Available drivers are registered with a driver manager. One
interesting point to note is that a driver does not necessarily need to interact with a DBMS that
understands SQL. It is sufficient that the driver translates the SQL commands from the
application into equivalent commands that the DBMS understands. Therefore, in the
An application that interacts with a data source through ODBC or JDBC selects a data source,
dynamically loads the corresponding driver, and establishes a connection with the data source.
There is no limit on the number of open connections, and an application can have several open
connections to different data sources. Each connection has transaction semantics; that is, changes
from one connection are visible to other connections only after the connection has committed its
changes. While a connection is opcn, transactions are executed by submitting SQL statements,
retrieving results, processing errors, and finally committing or rolling back. The application
disconnects from the data source to terminate the interaction.
6.2.1 Architecture
• the application,
• thedriver manager,
• several data source specific dr-iveTs,
• and the corresponding
• data SOURces.
The application initiates and terminates the connection with a data source. It sets transaction
boundaries, submits SQL statements, and retrieves the results-----all through a well-defined
interface as specified by the JDBC API. The primary goal of the dr-iver manager is to load
JDBC drivers and pass JDBC function calls from the application to the correct driver. The driver
manager also handles JDBC initialization and information calls from the applications and can log
all function calls. In addition, the driver manager performs· some rudimentary error checking.
The dr-iver establishes the connection with the data source. In addition to submitting requests
The data source processes commands from the driver and returns the results.Depending on the
relative location of the data source and the application, several architectural scenarios are
possible. Drivers in JDBC are cla.ssified into four types depending on the architectural
relationship between the application and the data source:
Type I Bridges: This type of driver translates JDBC function calls into function calls of another
API that is not native to the DBMS. An example is a JDBC-ODBC bridge; an application can
use JDBC calls to access an ODBC compliant data source. The application loads only one driver,
the bridge. Bridges have the advantage that it is easy to piggyback the applica.tion onto an
existing installation, and no new drivers have to be installed.drawbacks. The increased number of
layers between data source and application affects performance. In addition, the user is limited to
the functionality that the ODBC driver supports.
Type II Direct Thanslation to the Native API via Non-Java Driver: This type of driver
translates JDBC function calls directly into method invocations of the API of one specific data
source. usually ,vritten using a combination of C++ and Java; it is dynamically linked and
specific to the data source.
This architecture performs significantly better than a JDBC-ODBC bridge. One disadvantage is
that the database driver that implements the API needs to be installed on each computer that runs
the application.
Type III..Network Bridges: The driver talks over a network to a middleware server that
translates the JDBC requests into DBMS-specific method invocations. In this case, the driver on
the client site (Le., thenetwork bridge) is not DBMS-specific. The JDBC driver loaded by the
ap~ plication can be quite small, as the only functionality it needs to implement is sending of
SQL statements to the middleware server. The middleware server can then use a Type II JDBC
driver to connect to the data source.
JDBC is a collection of Java classes and interfaces that enables database access from prograrl1s
written in the Java language. It contains methods for connecting to a remote data source,
executing SQL statements, examining sets of results from SQL statements, transaction
management, and exception handling. The cla.sses and interfaces are part of the java. sql
package.
.
6.3.1 JDBC Driver Management
In .lDBe, data source drivers are managed by the Drivermanager class, which maintains a list of
all currently loaded drivers. The Drivermanager cla.ss has methods registerDriver,
deregisterDriver, and getDrivers to enable dynamic addition and deletion of drivers.
The first step in connecting to a data source is to load the corresponding JDBC driver. This is
accomplished by using the Java mechanism for dynamically loading classes. The static method
forName in the Class class returns the Java class as specified in the argument string and executes
its static constructor. The static constructor of the dynamically loaded class loads an instance of
the Driver class, and this Driver object registers itself with the DriverManager class.
6.3.2 Connections
A session with a data source is started through creation of a Connection object;A connection
identifies a logical session with a data source; multiple connections within the same Java
program can refer to different data sources or the samedata source.
Connections are specified through a JDBC URL, a URL that uses the jdbc protocol. Such a URL
has the form
jdbc:<subprotocol>:<otherParameters>
For example,
The Connection class has methods to set the
These two functions get and set the current level of isolation for transactions handled in the
current connection. All five SQL levels of isolation are possible, and argument 1 can be
set as follows:
- TRANSACTIONJNONE
- TRANSACTIONJREAD.UNCOMMITTED
- TRANSACTIONJREAD.COMMITTED
- TRANSACTIONJREPEATABLEJREAD
- TRANSACTION.BERIALIZABLE
These two functions allow the user to specify whether the transactions executecl through this
connection are rcad only.
public boolean isClosed() throws SQLException. Checks whether the current connection has
already been closed. setAutoCommit and get AutoCommit. we already discussed these two
functions. Establishing a connection to a data source is a costly operation since it involves
several steps, such as establishing a network connection to the data source, authentication, and
allocation of resources such as memory.
• Statement,
• PreparedStatement,
• CallableStatement.
The Statement
This class is the base class for the other two statment classes. It allows us to query the data
source with any static or dynamically generated SQL query.
The PreparedStatement cla,Cis dynamicaJly generates precompiled SQL statements that can be
used several times; these SQL statements can have parameters, but their structure is fixed when
the PreparedStatement object (representing the SQL statement) is created.
Consider the sample code using a PreparedStatment object The SQL query specifies the query
string, but uses ''1' for the values of the parameters, which are set later using methods setString,
setFloat, and setlnt. The ''1' placeholders can be used anywhere in SQL statements where they
can be replaced with a value. Examples of places where they can appear include the WHERE
clause (e.g., 'WHERE author=?'), or in SQL UPDATE and INSERT staternents, as in Figure 6.3.
The method setString is one way
Figure 6.3 SQL Update Using a PreparedStatement Object to set a parameter value; analogous
methods are available for int, float, and date. It is good style to always use clearParameters 0
before setting parameter values in order to remove any old data. There are different ways of
submitting the query string to the data source. In the example, we used the executeUpdate
command, which is used if we know that the SQL statement does not return any records (SQL
UPDATE, INSERT, ALTER, and DELETE statements). The executeUpdate method returns an
integerindicating the number of rows the SQL statement modified; it returns 0 forsuccessful
execution without modifying any rows.
The executeQuery method is used if the SQL statement returns data, such &"l in a regular
SELECT query. JDBC has its own cursor mechanism in the form of a ResultSet object, which
we discuss next. The execute method is more general than executeQuery and executeUpdate; the
references at the end of the chapter provide pointers with more details.
6.3.4 Resul,tSets
While next () allows us to retrieve the logically next row in the query answer,
We can move about in the query answer in other ways too:
• previous 0 moves back one row.
• absolute (int num) moves to the row with the specified number.
• relative (int num) moves forward or backward (if num is negative) relative to the current
position. relative (-1) has the same effect as previous.
• first 0 moves to the first row, and last 0 moves to the last row.
An SQL Warning is a subclass of SQLException. Warnings are not H•.'3 severe as errors
and the program can usually proceed without special handling of warnings.Warnings are not
thrown like other exceptions, and they are not caught a., part of the try"-catch block around a
java. sql statement.
Typical code for obtaining SQLWarnings looks similar to the code shown inFigure 6.6.
try {
stmt = con.createStatement();
warning = con.getWarnings();
while( warning != null) {
/ / handleSQLWarnings / / code to process warning
warning = warning.getNextWarningO; / /get next warning
}
con.clear\Varnings() ;
stmt.executeUpdate( queryString );
warning = stmt.getWarnings();
while( warning != null) {
/ / handleSQLWarnings / / code to process warning
warning = warning.getNextWarningO; / /get next warning
We can use tlw DatabaseMetaData object to obtain information about the database system itself,
as well as information frorn the database catalog. For example, the following code fragment
shows how to obtain the name and driver version of the JDBC driver:
Databa..seMetaData md = con.getMetaD<Lta():
System.out.println("Driver Information:");
System.out.println("Name:" + md.getDriverNameO
+ "; version:" + mcl.getDriverVersion());
The DatabaseMetaData object has many more methods (in JDBC 2.0, exactly
134); we list some methods here:
example code fragment that examines all database metadata shown in Figure 6.7.
6.4 SQLJ
SQLJ (short for 'SQL-Java') was developed by the SQLJ Group, a group of database vendors and
Sun. SQLJ was developed to complement the dynamic way of creating queries in JDBC with a
static model. It is therefore very close to Embedded SQL. Unlike JDBC, having semi-static SQL
queries allows the compiler to perform SQL syntax checks, strong type checks of the
compatibility of the host variables with the respective SQL attributes, and consistency of the
query with the database schema-tables, attributes, views, and stored procedures--all at
compilation time.
#sql books = {
SELECT title, price INTO :title, :price
FROM Books WHERE author = :author
};
In JDBC, we can dynamically decide which host language variables will hold
the query result. In the following example, we read the title of the book into
variable ftitle if the book was written by Feynman, and into variable otitle
otherwise:
/ / assume we have a ResultSet cursor rs
author = rs.getString(3);
if (author=="Feynman") {
ftitle = rs.getString(2):
}
else {
otitle = rs.getString(2);
}
when writing SQLJ applications, we just write regular Java code and embed SQL statements
according to a set of rules. SQLJ applications are pre-processed through an SQLJ translation
program that replaces the embedded SQLJ code with calls to an SQLJ Java library. The modified
program code can then be compiled by any Java compiler. Usually the SQLJ Java library makes
calls to a JDBC driver, which handles the connection to the datab&'3e system.
We will introduce SQLJ by means of examples. Let us start with an SQLJ code fragment that
selects records from the Books table that match a given author.
• Declare the Iterator Class: In the preceding code, this happened through the statement
#sql iterator Books (String title, Float price);
This statement creates a new Java class that we can use to instantiate objects.
• Instantiate an Iterator Object from the New Iterator Class: We instantiated our iterator in the
statement Books books;.
• Initialize the Iterator Using a SQL Statement: In our example, this happens through the
statement #sql books ;;;;;; ....
• Iteratively, Read the Rows From the Iterator Object: This step is very similar to reading rows
through a ResultSet object in JDBC.
• Close the Iterator Object.
There are two types of iterator classes: named iterators and positional iterators.
For named iterators, we specify both the variable type and the name of each
column of the iterator. This allows us to retrieve individual columns by name as
in our previous example where we could retrieve the title colunm from the Books
table using the expression books. titIe ().
we then retrieve the individual rows from the iterator 3,.'3 follows:
while (true) {
#sql { FETCH :books INTO :title, :price, };
if (books.endFetch()) {
break:
}
/ / process the book
}
It is often important to execute some parts of the application logic directly in the process space of
the database system. Running application logic directly at the databa.se has the advantage that
the amount of data that is transferred between the database server and the client issuing the SQL
statement can be minimized, while at the same time utilizing the full power of the databa.se
server. When SQL statements are issued from a remote application, the records in the result of
the query need to be transferred from the database system back to the application.
If we use a cursor to remotely access the results of an SQL statement, the DBMS has resources
such as locks and memory tied up while the application is processing the records retrieved
through the cursor. In contrast, a stored procedure is a program that is executed through a single
SQL statement that can be locally executed and completed within the process space of the
database server. The results can be packaged into one big result and returned to the application,
or the application logic can be performed directly at the server, without having to transmit the
results to the client at alL Stored procedures are also beneficial for software engineering rea,sons.
In addition, application programmers do not need to know the the databa.se schema if we
encapsulate all databa.'3e access into stored procedures. Although they,are called stored
procedur'es, they do not have to be procedures in a programming language sense; they can be
functions.
Let us look at the example stored procedure written in SQL shown in Figure(i.S. vVe see that
stored procedures must have a name; this stored procedurehas the name 'ShowNumberOfOrders.'
Otherwise, it just contains an SQLstatement that is precompiled and stored at the server.
Stored procedures can also have parameters. These parameters have to be valid SQL types,
and have one of three different modes: IN, OUT, or INOUT. IN parameters are arguments to' the
stored procedure. OUT parameters are returned from the stored procedure; it assigns values to all
OUT parameters that the user can process. INOUT parameters combine the properties of IN and
OUT parameters: They contain values to be passed to the stored procedures, and the stored
procedure can set their values as return values. Stored procedures enforce strict type
conformance: If a parameter is of type INTEGER, it cannot be called with an argument of type
VARCHAR. Let us look at an example of a stored procedure with arguments.
Stored procedures do not have to be written in SQL; they can be written in any host language. As
an example, the stored procedure shown in Figure 0.10 is a Java function that is
dynamicallyexecuted by the databa.<. ;e server whenever itis called by the dient:
Stored procedures can be called in interactive SQL with the CALL statement:
CREATE PROCEDURE RallkCustomers(IN number INTEGER)
LANGUAGE Java
EXTERNAL NAME 'file:/ / /c:/storedProcedures/rank.jar'
Figure 6.10 A Stored Procedure in Java
Each parameter is a triple consisting of the the parameter name, and the SQL datatype of the
parameter. We can seen very simple SQL/PSM procedures in Section6.5.1. In this case, the local
variable declarations were empty, and the procedure code consisted of an SQL query.
We start out with an example of a SQL/PSM function that illustrates the main SQL/PSM
constructs. The function takes as input a customer identified by her cid and a year. The function
returns the rating of the customer, which is defined a...'3 follows: Customers who have bought
more than ten books during the year are rated 'two'; customer who have purcha...<;ed between 5
and 10 books are rated 'one', otherwise the customer is rated 'zero'. The following SQL/PSM
code computes the rating for a given customer and year.
Let us use this example to give a short overview of some SQL/PSM constructs:
• We can declare local variables using the DECLARE statement. In our example,
we declare two local variables: 'rating', and 'numOrders'.
• PSM/SQL functions return values via the RETURN statement. In our example,
we return the value of the local variable 'rating'.
• vVe can assign values to variables with the SET statement. In our example,
we assigned the return value of a query to the variable 'numOrders'.
• SQL/PSM h&<; branches and loops. Branches have the following form:
IF (condition) THEN statements;
ELSEIF statements;
ELSEIF statements;
ELSE statements; END IF
Loops are of the form
LOOP
staternents:
END LOOP
• Queries can be used as part of expressions in branches; queries that return a single ;ralue can be
assigned to variables as in our example above.
• 'We can use the same cursor statements &s in Embedded SQL (OPEN, FETCH,
DBDudes finished logical database design, as discussed in Section 3.8, and now consider the
queries that they have to support. They expect that the application logic will be implemented in
Java, and so they consider JDBC and SQLJ as possible candidates for interfacing the database
system with application code. Recall that DBDudes settled on the following schema:
Now, DBDudes considers the types of queries and updates that will arise. They first create a list
of tasks that will be performed in the application. Tasks performed by customers include the
following. II Customers search books by author name, title, or ISBN. .. Customers register with
the website. Registered customers might want to change their contact information. DBDudes
realize that they have to augment the Customers table with additional information to capture
login and password information for each customer; we do not discuss this aspect any further.
Placing an order involves inserting one or more records into the Orders table. Since DBDudes
has not yet chosen the Java-based technology to program the application logic, they assume for