Advanced SQL
Advanced SQL
2. Unavailable or withheld value: A person has a home phone but does not want it to be
listed, so it is withheld and represented as NULL in the database.
3. Not applicable attribute: An attribute LastCollegeDegree would be NULL for a person who
has no college degrees, because it does not apply to that person.
In (a) and (b), the rows and columns represent the values of the results of 2 three valued Boolean
expressions which would appear in the WHERE clause of an SQL query. Each expression result would have
a value of true, false, or unknown.
Page 1
In select-project-join queries, the general rule is that only those combinations of tuples that evaluate
the logical expression of the query to TRUE are selected. Tuple combinations that evaluate to FALSE
or UNKNOWN are not selected. There are exceptions to that rule for certain operations such as outer joins.
Query 1: Retrieve the names of all employees who do not have supervisors.
Nested queries are complete select-from-where blocks within another SQL query. That other query
is called the outer query. The nested queries can also appear in the WHERE clause of the FROM
clause or other SQL clauses as needed.
The comparison operator IN compares a value v with a set (or multiset) of values V and evaluates to
TRUE if v is one of the elements in V.
OR
Pnumber IN
(SELEC T Pno
FROM WORKS ON, EMPLOYEE
WHERE Essn=Ssn AND Lname='Smith');
Page 2
If a nested query returns a single attribute and a single tuple, the query result will be a single value.
In such cases, = can be used instead of IN for the comparison operator. In general, a 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 in parentheses. This is
illustrated in the query below.
Query 3:Retrieve the Ssns of all employee who work on the same (project, hours) combination on
some project that employee 'John Smith' whose Ssn is 123456789 works on.
SEL EC T D I ST IN CT Essn
FROM WORKS ON
W H E R E ( P n o , H o u r s ) I N ( SE L E C T P n o , H o u r s
FROM WORKS ON
WHER E Es s n = ' 1 2 3 4 5 6 7 8 9 ' ) ;
In this example, the IN operator compares the sub-tuple of values in parentheses (Pno, Hours) for
each tuple in WORKS_ON with the set of union compatible tuples produced by the nested query.
Query 4: Retrieve the names of employees whose salary is greater than the salary of all the
employees in department 5.
SEL EC T Ln a m e , Fn a m e
FROM EMPLOYEE
WHERE S a l ar y > ALL (SELEC T S a la ry
FROM EMPLOYEE
WHERE Dno = 5 ) ;
If attributes of the same name exist, one in the FROM clause of the nested query and one in the FROM
clause of the outer query, then there arises ambiguity in attribute names. The rule is that the reference
to an unqualified attribute refers to the relation declared in the innermost nested query. It is generally
advisable to create tuple variables (aliases) for all the tables referenced in an SQL query to avoid
errors and ambiguities.
Page 3
Query 5: Retrieve the name of each employee who has a dependent with the same first name
and sex as the employee.
SELECT E . Ln a m e, E . Fn a m e
FROM EMPLOYEE AS E
WHERE E . S s n I N ( SELE CT E s s n
FROM DEPENDENT
WHERE E . F n a me = D e p e n d en t n a me AN D E . S e x = S e x ) ;
3. Correlated Nested Queries:
Whenever a condition in the WHERE clause of a nested query references some attribute of a
relation declared in the outer query, the two queries are said to be correlated.
For a correlated nested query, the nested query is evaluated once for each tuple (or
combination of tuples) in the outer query.
Example: In Query 5, for each EMPLOYEE tuple, evaluate the nested query, which retrieves the Essn
values for all DEPENDENT tuples with the same sex and name as that EMPLOYEE tuple; if the SSN
value of the EMPLOYEE tuple is in the result of the nested query, then select that EMPLOYEE tuple.
In general, a query written with nested select-from-where blocks and using the = or IN comparison
operators can always be expressed as a single block query. The query below is another way of solving
Query 5.
SELECT E . Fn a m e, E . Ln a m e
FROM EMPLOYEE AS E, DEPENDENT AS D
WHERE E . Ssn = D. E ssn AND E . Sex= D. Sex
AN D E . F n a m e = D . D e p e n d e n t n a m e ;
EXISTS (Q) returns TRUE if there is atleast one tuple in the result of the nested query
Q and returns FALSE otherwise.
NOT EXISTS ( Q) returns TRUE if there are no tuples in the result of the nested query
Q and returns FALSE otherwise.
Page 4
Query 5 can be written in an alternative form that uses EXISTS. The nested query
references the Ssn, Fname, and Sex attributes of the EMPLOYEE relation from the outer
query. For each employee tuple, evaluate the nested query which retrieves all
DEPENDENT tuples with the same Essn, Sex and Dependent_name as the employee
tuple; if atleast 1 tuple EXISTS in the result of the nested query, then select that employee
tuple.
SE L E C T E . F n a m e , E . L n a m e FROM EMPLOYEE AS E
WH ER E EXI STS ( SE L EC T * FROM DEPENDENT AS D
WH E R E E . S s n = D . E s s n AND E . S e x = D . S e x
AND
E. Fna me= D.Depen dentnam e);
Query 7: List the names of managers who have atleast one dependent.
SELECT FNAME, LNAME
FROM EMPLOYEE
WHEREEXISTS ( SEL EC T * FROM DEPENDENT
WHERE SSN=ESSN)
AND EXISTS (SELECT FROM DEPARTMENT
WHERE S s n = M g r s s n ) ;
Query 8: Retrieve the name of each employee who works on all the projects
controlled by department number 5.
Page 5
The function UNIQUE (Q) returns TRUE if there are no duplicate tuples in the result of query Q;
otherwise it returns FALSE.
The UNIQUE function can be used to test whether the result of a nested query is a set — no
duplicates or a multiset — duplicates exist.
In SQL, it is possible to rename any attribute that appears in the result of a query by adding the
AS qualifier followed by the desired new name.
AS construct can be used to alias both attribute and relation names in general and it can be used in
appropriate parts of a query.
SELECT E.Lname AS Employee name, S.Lname AS
Supervisor name FROM EMPLOYEE AS E, EMPLOYEE AS
S
WHERE E.Superssn=S.Ssn;
The attributes of such a table are all the attributes of the first table EMPLOYEE
followed by all attributes of the second table DEPARTMENT.
Page 6
If the names of join attributes are not the same in base relations, rename the attributes so
that they match and then apply the NATURAL JOIN. The AS construct can be used to
rename a relation and all its attributes in the FROM clause.
Example: Here the DEPARTMENT relation is renamed as DEPT and its attributes are
renamed as Dname , Dno, Mssn and Msdate. The implied join condition for this natural join is
EMPLOYEE. Dno = DEPT. Dno because it is the only pair of attributes with the same name.
The default type of join in a joined table is an INNER JOIN where a tuple is included in the
result only if a matching tuple exists in the other relation. If every tuple should be included in the
result, OUTER JOIN must be explicitly specified.
LEFT OUTER JOIN — every tuple in the left table must appear in the result. If it does
not have a matching tuple, it is padded with NULL values for the attributes of the right
table.
RIGHT OUTER JOIN every tuple in the right table must appear in the result. If it does
-
not have a matching tuple, it is padded with NULL values for the attributes of the left table.
F U L L OUTER JOIN. The keyword OUTER may be omitted in LEFT OUTER JOIN or RIGHT
: • If the join attributes have the same name, we can specify the natural join variation of outer
joins by using the keyword NATURAL before the operation. Eg: NATURAL LEFT OUTER
JOIN.
Page 7
Join specifications can be nested where one of the tables in a join may itself be a joined table.
This allows the specification of the join of three or more tables as a single joined table which is called
a multiway join.
Example:
SELECT PNUMBER, DNUM, LNAME, BDATE, ADDRESS
FROM((PROJECT JOIN DEPARTMENT ON DNUM=DNUMBER) JOIN
EMPLOYEE ON MGRSSN=SSN)
WHERE PLOCATION='Stafford';
Some SQL implementations have a different syntax to specify outer joins by using the comparison
operators += for left outer join, =+ for right outer join and +=+ for full outer join when specifying the
join condition.(Eg: Oracle uses this syntax)
Example:
SELECT E .Lname, S.Lname FROM
EMPLOYEE E, EMPLOYEE S W H E R E
E . S u pe r ss n + = S. S s n;
NULL values are discarded when aggregate functions are applied to a particular column
(attribute). COUNT (*) counts tuples not values hence NULL values do not affect it.
When an aggregate function is applied to a collection of values, NULLs are removed from the
collection before the calculation. If the collection becomes empty because all values are NULL,
Page 8
the aggregate function will return NULL except COUNT which returns a 0 for an empty
collection of values.
Aggregate functions can also be used in selection conditions involving nested queries. A correlated
nested query with an aggregate function can be specified and then used in the WHERE clause of
an outer query.
SQL also has aggregate functions SOME and ALL that can be applied to a collection of Boolean
values. SOME returns TRUE if atleast one element in the collection is TRUE whereas ALL returns
TRUE if all elements in the collection are TRUE.
Here the asterisk (*) refers to the rows (ttiples), so COUNT (*) returns the number of rows in
the result of the query. The COUNT function can also be used to count values in a column rather
than tuples.
Page 9
Query14 : Count the number of distinct salary values in the database.
SELE CT CO UNT ( DIS TINCT S a l a r y) FROM EMPLOYEE;
COUNT (Salary) will not eliminate duplicate values of Salary. Any tuples with NULL for Salary will not
be counted.
Query 15: Retrieve the names of all employees who have two or more
dependents.
SELE CT L n a m e , F n a m e FROM EMPLOYEE
WHERE ( SELECT COUNT (*) FROM DE PE NDE NT
WH ERE S s n = E s s n ) > = 2 ;
The correlated nested query counts the number of dependents that each employee has. If the count is
greater than or equal to two, the employee tuple is selected.
Each group (or partition) will consist of tuples that have the same value of some attribute(s) called
the grouping attribute(s).The function is then applied to each subgroup independently to
produce summary information about each group.
SQL has a GROUP BY-clause for specifying the grouping attributes. These attributes must also
appear in the SELECT- clause so that the value resulting from applying each aggregate function
to a group of tuples appears along with the value of the grouping attribute(s).
If NULLs exist in the grouping attribute, then a separate group is created for all tuples with a
NULL value in the grouping attribute. Eg: If the EMPLOYEE tuple had NULL for the grouping
attribute Dno, there would be a separate group for those tuples in the result of Query 16.
To retrieve the values of aggregate functions for only those groups that satis.b, certain conditions,
SQL provides a HAVING clause which can appear in conjunction with a GROUP BY clause. The
HAVING clause is used for specifying a selection condition on groups (rather than on individual
tuples) of tuples associated with each value of the grouping attributes. HAVING provides a
condition on the summary information regarding the group of tuples associated with each value of
the grouping attributes. Only the groups that satisfy the condition are retrieved in the result of the
query.
Page 10
• The selection conditions in the WHERE clause limit the tuples to which functions are applied
but the HAVING clause serves to choose whole groups.
Query 16: For each department, retrieve the department number, the
number of employees in the department, and their average salary.
SELECT D n o , C O U N T ( * ) , A V G ( S a l a r y )
FROM EMPLOYEE GROUP B Y D n o ;
The EMPLOYEE tuples are divided into groups - each group having the same value for the
grouping attribute Dno. The COUNT and AVG functions are applied to each such group of
tuples separately. The SELECT clause includes only the grouping attribute and the functions
to be applied on each group of tuples.
Query 17: For each project, retrieve the project number, project name,
and the number of employees who work on that project.
SELECT P n um be r , Pn a m e, COUN T (*FROM PROJECT, WORKS ON
In this case, the grouping and functions are applied after the joining of the two relations.
Query 18 : For each project on which more than two employees work,
retrieve the project number, project name, and the number of employees
who work on that project.
SELECT P n u m b e r , P n a m e , C OU N T (* )
FROM PROJECT, WORKS ON WHERE Pn u m ber = Pn o
GR OU P BY P n u m b e r , P n a m e
HAVING C OU N T (*) > 2 ;
Query 19: For each project, retrieve the project number, the project
name and the number of employees from department 5 who work on the
project.
SELECT P n u m b e r , P n a m e , C OU N T (* )
FROM PROJECT, WORKS ON, EMPLOYEE
WHERE P n um be r = Pn o A N D S sn = E s sn A N D Dn o= 5
GROU P BY P n u m b e r , P n a m e ;
Query 20: For each department that has more than 5 employees,
retrieve the department number and the number of employees who are
making a salary more than $40,000.
Page 11
SELECT Dno, COUNT(*) FROM EMPLOYEE
WHERE S a l a r y > 4 0 0 0 0 A N D D n o IN(SELECT D n o
FROM EMPLOYEE GROUP BY Dno HAVING COUNT(*)>5)
GROUP BY Dno;
The WITH clause allows a user to define a table that will only be used in a particular query. This
table will be dropped after its use in that query.
Queries using WITH can generally be written using other SQL constructs.
Example:
WITH LARGE_DEPTS (Dno) AS (SELECT Dno FROM EMPLOYEE
GROUP BY Dno HAVING COUNT(*) > 5)
SELECT Dno, COUNT(*)
FROM EMPLOYEE
WHERE S a l a r y> 4 00 0 0 AND D no IN LARGE DEPTS
GROUP BY D n o ;
Here a temporary table LARGE_DEPTS is defined using the WITH clause whose result holds the
Dnos of departments with more than 5 employees. This table is then used in the subsequent query.
Once this query is executed the temporary table LARGE_DEPTS is discarded.
The SQL CASE construct can be used when a value can be different based on certain
conditions.
It can be used in any part of an SQL query where a value is expected, including when
querying, inserting or updating tuples.
Example: Suppose we want to give employees different raise amounts depending on which department
they work for. Employees in department 5 get a $2000 raise, those in department 4 get $1500
and those in department 1 get $3000. We can write the update operation as:
UPDATE EMPLOYEE
SET Sal ar y = CASE WHEN D n o = 5 THEN S a l a r y + 2 0 0 0
WHEN D no = 4 THEN S a l a r y + 1500 WHEN D no = 1 THEN S a l a r y
+ 3 0 0 0 ELSE S a l a r y+ 0 ;
Here the salary raise value is determined through the CASE construct based on the
department number for which each employee works.
The CASE construct can also be used when inserting tuples that can have different attributes
being NULL depending on the type of record being inserted into a table, as when a specialization
is mapped into a single table or when a union type is mapped into a relation.
Page 12
10. Recursive Queries in SQL
A recursive query can be written in SQL using WITH RECURSIVE construct. It allows users the
capability to specify a recursive query in a declarative manner.
A recursive relationship between tuples of the same type is the recursive relationship between an
employee and supervisor. This relationship is described by the foreign key S up r_s sn of the
EMPLOYEE relation.
UNION S E L E C T E . S s n , S . S u p s s n
Here the view SUP_EMP will hold the result of the recursive query. The view is initially empty. It
is first loaded with the first level (Supervisor, supervisee) Ssn combinations through the first
part (SELECT Super ssn, Ssn FROM EMPLOYEE) which is called the base query. This will
be combined via UNION with each successive level of supervisees through the second part, where the
view contents are joined again with the base values to get the second level combinations which are
UNIONed with the first level. This is repeated with successive levels until a fixed pint is reached where
no more tuples are added to the view. At this point the result of the recursive query is in the
view SUP EMP.
Select SQL Statement:
A query in SQL can consist of up to six clauses, but only the first two SELECT and FROM, are
mandatory. The clauses are specified in the following order:
SELECT<attribute list>
FROM<table list>
[WHERE <condition>]
[GROUP BY <grouping attribute(s)>]
[HAVING <group condition>]
Page 13
The select clause lists the attributes or functions to be retrieved.
The FROM clause specifies all the relations or tables needed in the query including joined
relations
but not those in nested queries.
The WHERE clause specifies the conditions for selection of tuples from these relations including join
conditions if needed.
GROUP BY specifies grouping attributes whereas HAVING specifies a condition on the groups being
selected rather than on the individual tuples.
The built in aggregate functions COUNT, SUM, AVG, MIN and MAX are used in conjunction with
grouping but they can also be applied to all the selected tuples in a query without the group by clause.
:* ORDER BY specifies an order for displaying the result of a query. It is applied at the end to sort
A query is evaluated conceptually by first applying the FROM clause followed by the WHERE
clause and then by the GROUP BY and HAVING.
events and conditions occur. This type of functionality is referred to as active databases.
Each assertion is given a constraint name and is specified via a condition similar to the
WHERE clause of an SQL query.
For example, to specify the constraint that "the salary of an employee must not be greater
than the salary of the manager of the department that the employee works for" in SQL, we can
write the following assertion:
Page 14
The constraint name SALARY_CONSTRAINT is followed by the keyword CHECK which is followed by
a condition in parentheses that must hold true on every database state for the assertion to be satisfied.
The constraint name can be used later to refer to the constraint or modify or drop it.
The DBMS is responsible for ensuring that the condition is not violated.
Any WHERE clause condition can be used but many constraints can be specified using the EXISTS
and NOT EXISTS style of SQL conditions.
Whenever some tuples in the database cause the condition in the ASSERTION to evaluate to FALSE,
the constraint is violated. The constraint is satisfied by a database state if no combination of
tuples in that database state violates the constraint.
To write an assertion, specify a query that selects any tuples that violate the desired condition.
By including this query inside a NOT EXISTS clause, the assertion will specify that the result of
this query must be empty so that the condition will always be TRUE. Thus the assertion is violated
if the result of the query isn't empty.
The CHECK clauses on attributes, domains and tuples are, checked in SQL only when tuples are
inserted or updated in a specific table. Hence constraint checking can be implemented more
efficiently by DBMS in these cases. The schema designer should use CHECK on attributes, domains
and tuples only when sure that the constraint can only be violated by insertion or updating of tuples and
use CREATE ASSERTION only in cases where it is not possible to use CHECK on attributes,
domains or tuples so that checks are implemented efficiently by DBMS.
2. Trigger in SQL:
The CREATE TRIGGER statement is used to specify the type of action to be taken
when certain events occur and when certain conditions are satisfied. For e.g., it may be useful to
specify a condition that, if violated, causes some user to be informed of the violation. A manager
may want to be informed if an employee's travel expenses exceed a certain limit by receiving a
message whenever this occurs. The action that the DBMS must take in this case is to send an
appropriate message to that user. The condition is thus used to monitor the database. Other
actions may be specified, such as executing a specific stored procedure or triggering other
updates.
Example: Suppose we want to check whenever an employee's salary is greater than the
salary of his or her direct supervisor in the COMPANY database. Several events can trigger this rule:
inserting a new employee record, changing an employee's salary, or changing an employee's
supervisor. Suppose that the action to take would be to call an external stored procedure
SALARYLVIOLAT ION, which will notify the supervisor. The trigger could then be written as below.
Page 15
CREATE TRIGGER SALARYLVIOLATION
BEFORE INSERT OR UPDATE OF SALARY, SUPERVISOR SSN ON
EMPLOYEE FOR EACH ROW
WHEN (NEW. SALARY > (SELECT SALARY FROM EMPLOYEE
WHERE SSN = NEW.SUPERVISOR SSN))
INFORM SUPERVISOR(NEW.Supervisor ssn, NEW.Ssn );
The trigger is given the name SALARY VIOLATION, which can be used to remove or deactivate
the trigger later.
A typical trigger which is regarded as an ECA (Event, Condition, Action) rule has three
components:
The event(s): These are usually database update operations that are explicitly applied to the
database. The person who writes the trigger must make sure that all possible events are accounted for.
In some cases, it may be necessary to write more than> one trigger to cover all possible cases. These
events are specified after the keyword BEFORE, which means that the trigger should be executed
before the triggering operation is executed. An alternative is to use the keyword AFTER, which
specifies that the trigger should be executed after the operation specified in the event is completed.
1. The condition that determines whether the rule action should be executed: Once the
triggering event has occurred, an optional condition may be evaluated. If no condition is
specified, the action will be executed once the event occurs. If a condition is specified, it is
first evaluated, and only if it evaluates to true will the rule action be executed. The condition is
specified in the WHEN clause of the trigger.
. The action to be taken: The action is usually a sequence of SQL statements, but it could also
be a database transaction or an external program that will be automatically executed. In this example,
the action is to execute the stored procedure INFORM SUPERVISOR.
Triggers can be used in various applications, such as maintaining database consistency, monitoring
database updates, and updating derived data automatically.
A trigger specifies an event, a condition and an action. The action is to be executed automatically if
the condition is satisfied when the event occurs.
CREATE TRIGGER <trigger name>
(AFTER/ BEFORE ) <triggering events> ON table
name [FOR EACH ROW ]
[WHEN <condition>]
<trigger actions>
Page 16
3.3 VIEWS (VIRTUAL TABLES) IN SQL
1. Concept of a View in SQL:
A view in SQL is a single table that is derived from other tables which could be base tables or
previously defined views.
A view does not necessarily exist in physical form; it is considered a virtual table, in contrast to base
tables, whose tuples are always physically stored in the database. This limits the possible update
operations that can be applied to views, but it does not provide any limitations on querying a view.
A view is a way of specifying a table that we need to reference frequently, even though it may not
exist physically.
Queries can be specified on a view which is specified as single table retrievals.
The view WORKS ON VIEW does not have new attribute names as it inherits the names of the
view attributes from the defining tables EMPLOYEE, PROJECT and WORKS ON.
CREATE VIEW WORKS ON VIEW
AS SELECT FNAME, LNAME, PNAME, HOURS
FROMEMPLOYEE, PROJECT, WORKS ON
WHERESSN=ESSN AND PNO=PNUMBER;
The view DEPT INFO explicitly specifies new attribute names using a one to one correspondence
between the attributes specified in the CREATE VIEW clause and those specified in the SELECT
clause of the query that defines the view.
Queries can be specified on views just as specifying queries involving base tables.
Page 17
Example: To retrieve the last name and first name of all employees who work on `ProductX'
project.
QV: SELEC T Fname, Lname
FROM WORKS ONI
WHERE Pname=' ProductX' ;
Advantages of view: It simplifies the specification of certain queries. It is also used as a security and
authorization mechanism.
A view should always be up to date i.e., if we modify the tuples in the base tables on which the
-
view is defined, the view must automatically reflect these changes. Hence a view is not realized at the
time of view definition but when we specify a query on the view.
+ It is the responsibility of the DBMS to ensure that a view is up-to-date and not of the
user to ensure that the view is up-to-date.
If a view is not needed, it can be removed by DROP VIEW command.
Eg: DROP VIE W WORKS ON VIEW;
The disadvantage of this approach is that it is inefficient for views defined via complex queries that
are time consuming to execute, especially if multiple queries are applied to the view within a short
time.
The other strategy, view materialization involves physically creating a temporary view table when the
view is first queried and keeping that table on the assumption that other queries on the view will
follow. Here, an efficient strategy to automatically update the view when the base tables are updated
must be developed to keep the view up- to- date. Incremental update has been developed to determine
what new tuples must be inserted, deleted or modified in a materialized view table when a change is
applied to one of the defining base tables. The view is generally kept as a materialized (physically
stored) table as long as it is being queried. If the view is not queried for a certain period of time, the
system may then automatically remove the physical table and recomputed from scratch when future
queries reference the view.
Page 18
Different strategies as to when a materialized view is updated are possible.
immediate update strategy updates a view as soon as the base tables are changed.
lazy update strategy updates the view when needed by a view query.
periodic update strategy updates the view periodically (in the latter strategy, a view
query may get a result that is not up-to-date).
+ A retrieval query against any view can always be issued. But issuing an INSERT,
DELETE, or UPDATE command on a view table is in many cases not possible.
In general, an update on a view defined on a single table without any aggregate functions can be
mapped to an update on the underlying base table under certain conditions.
For a view involving joins, an update operation may be mapped to update operations on the underlying
base relations in multiple ways. Hence, it is not possible for the DBMS to determine which of the
updates is intended.
Example: Suppose that we issue the command to update the Pname attribute of 'John Smith'
from ProductX' to 'Productr in the view WORKS_ONVIEW. This view update is shown in
UV1: UV': UPDATE WORKS ON1
SET P n a m e = ' Pr od u c t Y '
WHER E L n a m e = ' S m i t h ' AND F n a m e = ' J o h n ' A N D P n a m e = ' P r o d u c t X ' ;
This query can be mapped into several updates on the base relations to give the desired update effect
on the view. Some of these updates will create additional side effects that affect the result of other queries.
Two possible updates, (a) and (b), on the base relations corresponding to UVI are shown. Update (a)
relates 'John Smith' to the 'ProductY ' PROJECT tuple in place of the ' ProductX' PROJECT tuple and
is the most likely desired update.
(a) UPDATE WORKS ON
S E T P n o = ( SE L E C T P n u m b e r
FROM PROJECT WHE R E P n a m e = ' P r o d u c t Y ' )
WH E R E E s s n I N ( SE L E C T S s n FROM EMPLOYEE
W H E RE L n a m e = ’ S m i t h ' AN D F n a m e = ' J o h n ' )
AND P n o = ( SE L E CT P n u m b e r FROM PROJECT
WH E R E P n a m e = ' P r o d u c t X ' ) ;
(b) U P D ATE P R O J E C T
SE T P n a m e = ' P r o d u c t Y '
WH ER E P n a m e = ' P r o d u c t X ' ;
Page 19
Update (b) would also give the desired update effect on the view, but it accomplishes this by changing the
name of the ' ProductX' tuple in the PROJECT relation to ' Product Y'. It is quite unlikely that the
user who specified the view update UVI wants the update to be interpreted as in (b), since it also has
the side effect of changing all the view tuples with Pname ' ProductX'.
Some view updates may not make much sense. For example, modifying the To ta l_ Sa l attribute of
the DEPT_INFO view does not make sense because To ta l Sal is defined to be the sum of the individual
employee salaries. This request is shown as UV2:
UV2: UPDATE DEPT_INFO
SET T o t a l S a l = 1 0 0 0 0 0
WHERE Dn a m e= ' Re s ea r ch ;
A view update is feasible when only one possible update on the base relations can accomplish the
desired update effect on the view.
Whenever an update on the view can be mapped to more than one update on the underlying base
relations, it is usually not permitted.
A view with a single defining table is updatable if the view attributes contain the primary key of the
base relation, as well as all attributes with the NOT NULL constraint that do not have default values
specified.
Views defined on multiple tables using joins are generally not updatable.
Views defined using grouping and aggregate functions are not updatable.
In SQL, the clause WITH CHECK OPTION should be added at the end of the view definition if a
view is to be updated by INSERT, DELETE, or UPDATE statements. This allows the system to reject
operations that violate the SQL rules for view updates.
It is also possible to define a view table in the FROM clause of an SQL query. This is known as an in-
line view.
Page 20
A view can restrict a user to only see certain columns; for example, only the first name, last name,
and address of an employee may be visible as follows:
By creating an appropriate view and granting certain users access to the view and not the base tables,
they would be restricted to retrieving only the data specified in the view.
3.4 SCHEMA CHANGE STATEMENTS IN SQL The schema evolution commands available in SQL can be
used to alter a schema by adding or dropping tables, attributes, constraints and other schema elements.
If a base relation within a schema is not needed any longer, the relation and its definition can be
deleted by using the DROP TABLE command. The DEPENDENT relation can be removed by
issuing the following command:
If the RESTRICT option is chosen instead of CASCADE, a table is dropped only if it is not
referenced in any constraints (for example, by foreign key definitions in another relation) or
views. With the CASCADE option, all such constraints and views that reference the table are
dropped automatically from the schema, along with the table itself
The DROP command can also be used to drop other types of named schema elements, such as
constraints or domains.
The DROP TABLE command not only deletes all the records in the table if successful, but also
removes the table definition from the catalog.
Page 21
2. The ALTER Command:
The definition of a base table or of other named schema elements can be changed by using the ALTER
command.
For base tables, the possible alter table actions include adding or dropping a column (attribute), changing a
column definition, and adding or dropping table constraints.
For example, an attribute for keeping track of jobs of employees to the EMPLOYEE base
relation can be added in the COMPANY schema by using the command
A value for the new attribute JOB for each individual EMPLOYEE tuple must be entered. This can be done
either by specifying a default clause or by using the UPDATE command individually on each tuple.
If no default clause is specified, the new attribute will have NULLS in all the tuples of the relation
immediately after the command is executed; hence, the NOT NULL constraint is not allowed in this case.
A column can be dropped by choosing either the CASCADE or RESTRICT for drop behavior. If cascade is
chosen, all constraints and views that reference the column are dropped automatically from the schema along
with the column. If RESTRICT is chosen, the command is successful only if no views or constraints
reference the column.
For example, the attribute Address can be removed from the EMPLOYEE base table by using the
following command.
ALTER TABLE COMPANY.EMPLOYEE DROP COLUMN Address CASCADE;
A column definition can be altered by dropping an existing default clause or by defining a new default
clause.
ALTER TABLE COMP ANY. DEP ART MENT ALTER COLUMN M gr_s sn DROP default;
ALTER TABLE C OM PA N Y. D EPAR TM EN T ALTER COLUMN M gr_ ss n SET default
‘12345’;
A constraint specified on a table can be changed by adding or dropping a constraint. A constraint can be
dropped if it had been given a name when it was specified. For example, the constraint named
EMPSUPERFK can be dropped from the EMPLOYEE relation by
ALTER TABLE COMPANY. EMPLOYEE DROP CONSTRAINT EMPSUPER FK CASCADE;
We can redefine a replacement constraint by adding a new constraint to the relation, if needed. This is
specified by using the ADD keyword in the ALTER TABLE statement followed by the new constraint which
can be named or unnamed and can be of any of the table constraint types.
ALTER TABLE COMPANY. EMPLOYEE ADD CONSTRAINT EMPSUPERFK FO R EIGN KEY ( SU PER
SSN ) R E FE R ENC ES EM PLO Y EE( SSN ) ;
Page 22
3.5 ACCESSING DATABASES FROM APPLICATIONS
The use of SQL commands within a host language program is called Embedded SQL. Details of
Embedded SQL also depend on the host language.
1. Embedded SQL:
SQL statements (i.e. not declarations) can be used wherever statement in the host language is allowed (with a
few restrictions).
SQL statements must be early marked so that a pre-processor can deal with them before invoking the
compiler for the host language.
Any host language variables used to pass arguments into an SQL command must be declared in SQL. Some
special host language variables must be declared in SQL. For example, any error conditions arising during
SQL execution can be communicated back to the main application program in the host language.
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 from SQL
commands. SQL being set-oriented is addressed using cursors.
long c_sid;
short c rating;
float c age;
EXEC SQL END DECL ARE SECTION
The SQL-92 standard defines a correspondence between the host language types and SQL types for a number
of host languages. In the example, c sname has the type CHARACTER (20) when referred to in an SQL
statement, c_sid has the type INTEGER, c rating has the type SMALLINT, and c_age has the type REAL.
The SQL-92 standard recognizes two special variables for reporting errors when executing an SQL
statement, i.e. SQLCODE and SQLSTATE.
SQLCODE is defined to return some negative value when an error condition arises, without specifying
further just what error a particular negative integer denotes.
SQLSTATE associates predefined values with several common error conditions, thereby introducing some
uniformity to how errors are reported. One of these two variables must be declared.
Page 23
The appropriate C type of SQLCODE is long and the appropriate C type of SQLSTATE is char [6] , that is, a
character string five characters long.
EXEC SQL
INSERT INTO Sailors VALUES (:c sname, :c_sid, :c rating, :c age);
A semicolon terminates the command, as per the convention for terminating statements in C.
The SQLSTATE variable should be checked for errors and exceptions after each Embedded SQL statement.
SQL provides the WHENEVER command to simplify this tedious task.
2. Cursors:
The impedance mismatch problem occurs when embedding SQL statements in a host language like C,
because SQL operates on set of records, whereas languages like C do not cleanly support a set-ofrecords
abstraction. The solution is to provide a mechanism that allows us to retrieve rows one at a time from a
relation. This mechanism is called a cursor.
A cursor can be declared on any relation or on any SQL query.
Once a cursor is declared we can-
1) open it which positions the cursor just`before the first row
2) fetch the next row
3) move the cursor (to the next row, to the row after next n, to the first row, or to the previous
row, etc., by specifying additional parameters for the FETCH command)
A cursor essentially allows us to retrieve the rows in a table by positioning the cursor at a particular row and
reading its contents.
Page 24
Basic Cursor Definition and Usage:
Cursors enable us to examine, in the host language program, a collection of rows computed by an Embedded
SQL statement.
A cursor needs to be opened if the embedded statement is a SELECT (i.e. a query). Opening a cursor can be
avoided if the answer contains a single row.
INSERT, DELETE and UPDATE statements typically require no cursor although some variants of DELETE
and UPDATE use a cursor.
Example:
1. We can find the name and age of a sailor, specified by assigning value to the host variable c s
id as follows:
EXEC SQL SELECT S.sname, S.age INTO :c_sname,:c_age
FROM Sailors S
WHERE S.sid = C_sid
The INTO clause allows us to assign the columns of a single answer row to the host variables
c s name and c age. Therefore, we do not need a cursor to embed this query in a host language
program.
2. Consider a query, which computes the names and ages of all sailors with a rating greater than the
current value of the host variable c minrat ing.
SELECT S . sname, S.age
FROM Sailors S
WHERE S. rating > :c_minrating;
This query returns a collection of rows, not just one row. Hence a cursor needs to be used.
This code can be included in a C program, and once it is executed, the cursor sinfo is defined.
Subsequently, we can open the cursor:
OPEN sinfo;
The value of c minrating in the SQL query associated with the cursor is the value of this variable when
we open the cursor. (The cursor declaration is processed at compile-time, and the OPEN command is
executed at run-time.)
Page 25
When a cursor is opened, it is positioned just before the first row. We can use the FETCH command
to read the first row of cursor sinfo into host language variables:
FETCH sinfo INTO :csname, :c age;
When the FETCH statement is executed, the cursor is positioned to point at the next row (which is the first
row in the table when FETCH is executed for the first time after opening the cursor) and the column values in
the row are copied into the corresponding host variables. By repeatedly executing this FETCH statement
(say, in a while-loop in the C program), we can read all the rows computed by the query, one row at a time.
Additional parameters to the FETCH command allow us to position a cursor in very flexible ways.
The special variables SQLCODE and SQLSTATE indicate when we have looked at all the rows associated
with the cursor.
When we are done with a cursor, we can close it:
CLO SE sinfo;
It can be opened again if needed, and the value of : c_minrating in the SQL query associated with the cursor
would be the value of the host variable c_minrating at that time.
Properties of Cursors:
The general form of cursor declaration is:
DECLARE cursorname [INSENSITIVE] [SCROLL]
CURSOR [WITH HOLD]
FOR some query
[ORDER BY order-item-list]
[ FOR READ ONLY FOR UPDATE]
A cursor can be declared to be-
a read-only cursor (FOR READ ONLY) or,
an updatable cursor (FOR UPDATE) if it is a cursor on a base relation or an updatable
view.
If it is updatable, 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 sinfo is an updatable cursor and open, we can execute the following statement:
UPDATE Sailors S
SET S.rating = S.rating-1
WHERE CURRENT of sinfo;
This Embedded SQL statement modifies the rating value of the row currently pointed to by cursor
sinfo. We can delete this row by executing the next statement:
DELETE Sailors S
WHERE CURRENT of sinfo;
Page 26
A cursor is updatable by default unless it is scrollable, which means that variants of the FETCH command
can be used to position the cursor in very flexible ways; otherwise, only the basic FETCH command, which
retrieves the next row, is allowed.
If the keyword INSENSITIVE is specified, the cursor behaves as if it is ranging over a private copy of the
collection of answer rows. Otherwise, and by default, other actions of some transaction could modify these
rows, creating unpredictable behavior.
For example, while we are fetching rows using the s info cursor, we might modify rating
values in Sailor rows by concurrently executing the command.
UP D A T E Sa i l or s S S E T S . r a t i n g = S . r a t i n g - 1;
If INSENSITIVE is specified, the behaviour is as if all answers were computed and stored when
sinfo was opened; thus, the update command has no effect on the rows fetched by sinfo if it is
executed after s in f o is opened. If INSENSITIVE is not specified, the behaviour is implementation dependent
in this situation.
A holdable cursor is specified using the WITH HOLD clause, and is not closed when the transaction is
committed. This is needed for a long transaction in which we access (and possibly change) a large number of
rows of a table. We can break the transaction into several smaller transactions. The application program can
commit the transaction it initiated while retaining its handle on the active table (i.e. the cursor).
The order in which FETCH command retrieves rows, in general is unspecified, but the optional ORDER BY
clause can be used to specify a sort order. The columns mentioned in'the ORDER BY clause cannot be
updated through the cursor.
The order-item-list is a list of order-items; an order-item is a column name, optionally followed by one of the
keywords ASC or DESC. Every column mentioned in the ORDER BY clause must also appear in the select-
list of the query associated with the cursor, otherwise it is not clear what columns we should sort on. The
keywords ASC or DESC that follow a column control whether the result should be sorted-with respect to that
column-in ascending or descending order; the default is ASC. This clause is applied as the last step in
evaluating the query.
Page 27
3. Dynamic SQL:
An application such as a spreadsheet or a graphical front-end that needs to access data from a DBMS, accepts
commands from a user and, based on the user needs, generates appropriate SQL statements to retrieve the
necessary data. In such situations, it is not possible to predict in advance which SQL statements need to be
executed. SQL provides Dynamic SQL to deal with such situations.
The two main commands, PREPARE and EXECUTE are used:
char c_sqlstring[] = {"DELETE FROM Sailors WHERE rating > 5"};
EXEC SQL PREPARE readytogo FROM :c_sqlstring;
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. The third statement executes the command.
The preparation of a Dynamic SQL command occurs at run-time and is run-time overhead.
Interactive and Embedded SQL commands can be prepared once at compile-time and then re-executed as
often as desired.
The use of Dynamic SQL should be limited to situations in which it is essential.
Page 28