- endterm="rel-alg"> for more details).
-
-
- The qualifications in the WHERE clause can also be logically connected
- using the keywords OR, AND, and NOT:
-
-SELECT PNAME, PRICE
- FROM PART
- WHERE PNAME = 'Bolt' AND
- (PRICE = 0 OR PRICE <= 15);
-
-
- will lead to the result:
-
-
- PNAME | PRICE
---------+--------
- Bolt | 15
-
-
-
- Arithmetic operations can be used in the target list and in the WHERE
- clause. For example if we want to know how much it would cost if we
- take two pieces of a part we could use the following query:
-
-SELECT PNAME, PRICE * 2 AS DOUBLE
- FROM PART
- WHERE PRICE * 2 < 50;
-
-
- and we get:
-
-
- PNAME | DOUBLE
---------+---------
- Screw | 20
- Nut | 16
- Bolt | 30
-
-
- Note that the word DOUBLE after the keyword AS is the new title of the
- second column. This technique can be used for every element of the
- target list to assign a new title to the resulting
- column. This new title
- is often referred to as alias. The alias cannot be used throughout the
- rest of the query.
-
-
-
-
-
-
-
Joins
-
- The following example shows how joins are
-
-
- To join the three tables SUPPLIER, PART and SELLS over their common
- attributes we formulate the following statement:
-
-SELECT S.SNAME, P.PNAME
- FROM SUPPLIER S, PART P, SELLS SE
- WHERE S.SNO = SE.SNO AND
- P.PNO = SE.PNO;
-
-
- and get the following table as a result:
-
-
- SNAME | PNAME
--------+-------
- Smith | Screw
- Smith | Nut
- Jones | Cam
- Adams | Screw
- Adams | Bolt
- Blake | Nut
- Blake | Bolt
- Blake | Cam
-
-
-
- In the FROM clause we introduced an alias name for every relation
- because there are common named attributes (SNO and PNO) among the
- relations. Now we can distinguish between the common named attributes
- by simply prefixing the attribute name with the alias name followed by
- a dot. The join is calculated in the same way as shown in
- .
- First the Cartesian product
-
- SUPPLIER × PART × SELLS
-
- is derived. Now only those tuples satisfying the
- conditions given in the WHERE clause are selected (i.e., the common
- named attributes have to be equal). Finally we project out all
- columns but S.SNAME and P.PNAME.
-
-
- Another way to perform joins is to use the SQL JOIN syntax as follows:
-SELECT sname, pname from supplier
- JOIN sells USING (sno)
- JOIN part USING (pno);
-
- giving again:
-
- sname | pname
--------+-------
- Smith | Screw
- Adams | Screw
- Smith | Nut
- Blake | Nut
- Adams | Bolt
- Blake | Bolt
- Jones | Cam
- Blake | Cam
-(8 rows)
-
-
-
- A joined table, created using JOIN syntax, is a table reference list
- item that occurs in a FROM clause and before any WHERE, GROUP BY,
- or HAVING clause. Other table references, including table names or
- other JOIN clauses, can be included in the FROM clause if separated
- by commas. JOINed tables are logically like any other
- table listed in the FROM clause.
-
-
- SQL JOINs come in two main types, CROSS JOINs (unqualified joins)
- and qualified JOINs>. Qualified joins can be further
- subdivided based on the way in which the join condition>
- is specified (ON, USING, or NATURAL) and the way in which it is
- applied (INNER or OUTER join).
-
-
-
-
Join Types
-
- CROSS JOIN
-
-
- CROSS JOIN
-
-
- A cross join takes two tables T1 and T2 having N and M rows
- respectively, and returns a joined table containing all
- N*M possible joined rows. For each row R1 of T1, each row
- R2 of T2 is joined with R1 to yield a joined table row JR
- consisting of all fields in R1 and R2. A CROSS JOIN is
- equivalent to an INNER JOIN ON TRUE.
-
-
-
-
-
- Qualified JOINs
-
-
-
-
-
-
-
-
- JOIN
-
-
USING ( join column list )
-
-
-
- A qualified JOIN must specify its join condition
- by providing one (and only one) of NATURAL, ON, or
- USING. The ON clause
- takes a search condition,
- which is the same as in a WHERE clause. The USING
- clause takes a comma-separated list of column names,
- which the joined tables must have in common, and joins
- the tables on equality of those columns. NATURAL is
- shorthand for a USING clause that lists all the common
- column names of the two tables. A side-effect of both
- USING and NATURAL is that only one copy of each joined
- column is emitted into the result table (compare the
- relational-algebra definition of JOIN, shown earlier).
-
-
-
-
-
-
-
- JOIN
-
-
-
- For each row R1 of T1, the joined table has a row for each row
- in T2 that satisfies the join condition with R1.
-
-
- The words INNER and OUTER are optional for all JOINs.
- INNER is the default. LEFT, RIGHT, and FULL imply an
- OUTER JOIN.
-
-
-
-
-
-
-
- JOIN
-
-
-
- First, an INNER JOIN is performed.
- Then, for each row in T1 that does not satisfy the join
- condition with any row in T2, an additional joined row is
- returned with null fields in the columns from T2.
-
-
- The joined table unconditionally has a row for each row in T1.
-
-
-
-
-
-
-
- JOIN
-
-
-
- First, an INNER JOIN is performed.
- Then, for each row in T2 that does not satisfy the join
- condition with any row in T1, an additional joined row is
- returned with null fields in the columns from T1.
-
-
- The joined table unconditionally has a row for each row in T2.
-
-
-
-
-
-
-
- JOIN
-
-
-
- First, an INNER JOIN is performed.
- Then, for each row in T1 that does not satisfy the join
- condition with any row in T2, an additional joined row is
- returned with null fields in the columns from T2.
- Also, for each row in T2 that does not satisfy the join
- condition with any row in T1, an additional joined row is
- returned with null fields in the columns from T1.
-
-
- The joined table unconditionally has a row for every row of T1
- and a row for every row of T2.
-
-
-
-
-
-
-
-
-
-
-
- JOINs of all types can be chained together or nested where either or both of
- T1 and
- T2 can be JOINed tables.
- Parenthesis can be used around JOIN clauses to control the order
- of JOINs which are otherwise processed left to right.
-
-
-
-
-
-
Aggregate Functions
-
-
SQL provides aggregate functions such as AVG,
- COUNT, SUM, MIN, and MAX. The argument(s) of an aggregate function
- are evaluated at each row that satisfies the WHERE
- clause, and the aggregate function is calculated over this set
- of input values. Normally, an aggregate delivers a single
- result for a whole SELECT statement. But if
- grouping is specified in the query, then a separate calculation
- is done over the rows of each group, and an aggregate result is
- delivered per group (see next section).
-
-
-
Aggregates
-
- If we want to know the average cost of all parts in table PART we use
- the following query:
-
-SELECT AVG(PRICE) AS AVG_PRICE
- FROM PART;
-
-
-
- The result is:
-
-
- AVG_PRICE
------------
- 14.5
-
-
-
- If we want to know how many parts are defined in table PART we use
- the statement:
-
-SELECT COUNT(PNO)
- FROM PART;
-
-
- and get:
-
-
- COUNT
--------
- 4
-
-
-
-
-
-
-
-
-
Aggregation by Groups
-
-
SQL allows one to partition the tuples of a table
- into groups. Then the
- aggregate functions described above can be applied to the groups —
- i.e., the value of the aggregate function is no longer calculated over
- all the values of the specified column but over all values of a
- group. Thus the aggregate function is evaluated separately for every
- group.
-
-
- The partitioning of the tuples into groups is done by using the
- keywords GROUP BY followed by a list of
- attributes that define the
- groups. If we have
- GROUP BY A1, ⃛, Ak
- we partition
- the relation into groups, such that two tuples are in the same group
- if and only if they agree on all the attributes
- A1, ⃛, Ak.
-
-
-
Aggregates
- If we want to know how many parts are sold by every supplier we
- formulate the query:
-
-SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
- FROM SUPPLIER S, SELLS SE
- WHERE S.SNO = SE.SNO
- GROUP BY S.SNO, S.SNAME;
-
-
- and get:
-
-
- SNO | SNAME | COUNT
------+-------+-------
- 1 | Smith | 2
- 2 | Jones | 1
- 3 | Adams | 2
- 4 | Blake | 3
-
-
-
- Now let's have a look of what is happening here.
- First the join of the
- tables SUPPLIER and SELLS is derived:
-
-
- S.SNO | S.SNAME | SE.PNO
--------+---------+--------
- 1 | Smith | 1
- 1 | Smith | 2
- 2 | Jones | 4
- 3 | Adams | 1
- 3 | Adams | 3
- 4 | Blake | 2
- 4 | Blake | 3
- 4 | Blake | 4
-
-
-
- Next we partition the tuples into groups by putting all tuples
- together that agree on both attributes S.SNO and S.SNAME:
-
-
- S.SNO | S.SNAME | SE.PNO
--------+---------+--------
- 1 | Smith | 1
- | 2
---------------------------
- 2 | Jones | 4
---------------------------
- 3 | Adams | 1
- | 3
---------------------------
- 4 | Blake | 2
- | 3
- | 4
-
-
-
- In our example we got four groups and now we can apply the aggregate
- function COUNT to every group leading to the final result of the query
- given above.
-
-
-
-
- Note that for a query using GROUP BY and aggregate
- functions to make sense, the target list can only refer directly to
- the attributes being grouped by. Other attributes can only be used
- inside the arguments of aggregate functions. Otherwise there would
- not be a unique value to associate with the other attributes.
-
-
- Also observe that it makes no sense to ask for an aggregate of
- an aggregate, e.g., AVG(MAX(sno)), because a
- SELECT only does one pass of grouping and
- aggregation. You can get a result of this kind by using a
- temporary table or a sub-SELECT in the FROM clause to do the
- first level of aggregation.
-
-
-
-
-
Having
-
- The HAVING clause works much like the WHERE clause and is used to
- consider only those groups satisfying the qualification given in the
- HAVING clause. Essentially, WHERE filters out unwanted input rows
- before grouping and aggregation are done, whereas HAVING filters out
- unwanted group rows post-GROUP. Therefore, WHERE cannot refer to the
- results of aggregate functions. On the other hand, there's no point
- in writing a HAVING condition that doesn't involve an aggregate
- function! If your condition doesn't involve aggregates, you might
- as well write it in WHERE, and thereby avoid the computation of
- aggregates for groups that you're just going to throw away anyway.
-
-
-
Having
-
- If we want only those suppliers selling more than one part we use the
- query:
-
-SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
- FROM SUPPLIER S, SELLS SE
- WHERE S.SNO = SE.SNO
- GROUP BY S.SNO, S.SNAME
- HAVING COUNT(SE.PNO) > 1;
-
-
- and get:
-
-
- SNO | SNAME | COUNT
------+-------+-------
- 1 | Smith | 2
- 3 | Adams | 2
- 4 | Blake | 3
-
-
-
-
-
-
-
-
Subqueries
-
- In the WHERE and HAVING clauses the use of subqueries (subselects) is
- allowed in every place where a value is expected. In this case the
- value must be derived by evaluating the subquery first. The usage of
- subqueries extends the expressive power of
-
-
-
Subselect
-
- If we want to know all parts having a greater price than the part
- named 'Screw' we use the query:
-
-SELECT *
- FROM PART
- WHERE PRICE > (SELECT PRICE FROM PART
- WHERE PNAME='Screw');
-
-
-
- The result is:
-
-
- PNO | PNAME | PRICE
------+---------+--------
- 3 | Bolt | 15
- 4 | Cam | 25
-
-
-
- When we look at the above query we can see the keyword
- SELECT two times. The first one at the
- beginning of the query - we will refer to it as outer
- SELECT - and the one in the WHERE clause which
- begins a nested query - we will refer to it as inner
- SELECT. For every tuple of the outer
- SELECT the inner SELECT has
- to be evaluated. After every evaluation we know the price of the
- tuple named 'Screw' and we can check if the price of the actual
- tuple is greater. (Actually, in this example the inner query need
- only be evaluated once, since it does not depend on the state of
- the outer query.)
-
-
- If we want to know all suppliers that do not sell any part
- (e.g., to be able to remove these suppliers from the database) we use:
-
-SELECT *
- FROM SUPPLIER S
- WHERE NOT EXISTS
- (SELECT * FROM SELLS SE
- WHERE SE.SNO = S.SNO);
-
-
-
- In our example the result will be empty because every supplier
- sells at least one part. Note that we use S.SNO from the outer
- SELECT within the WHERE clause of the inner
- SELECT. Here the subquery must be evaluated
- afresh for each tuple from the outer query, i.e., the value for
- S.SNO is always taken from the current tuple of the outer
- SELECT.
-
-
-
-
-
-
-
Subqueries in FROM
-
- A somewhat different way of using subqueries is to put them in the
- FROM clause. This is a useful feature because a subquery of this
- kind can output multiple columns and rows, whereas a subquery used
- in an expression must deliver just a single result. It also lets
- us get more than one round of grouping/aggregation without resorting
- to a temporary table.
-
-
-
Subselect in FROM
-
- If we want to know the highest average part price among all our
- suppliers, we cannot write MAX(AVG(PRICE)), but we can write:
-
-SELECT MAX(subtable.avgprice)
- FROM (SELECT AVG(P.PRICE) AS avgprice
- FROM SUPPLIER S, PART P, SELLS SE
- WHERE S.SNO = SE.SNO AND
- P.PNO = SE.PNO
- GROUP BY S.SNO) subtable;
-
-
- The subquery returns one row per supplier (because of its GROUP BY)
- and then we aggregate over those rows in the outer query.
-
-
-
-
-
-
-
Union, Intersect, Except
-
- These operations calculate the union, intersection and set theoretic
- difference of the tuples derived by two subqueries.
-
-
-
Union, Intersect, Except
-
- The following query is an example for UNION:
-
-SELECT S.SNO, S.SNAME, S.CITY
- FROM SUPPLIER S
- WHERE S.SNAME = 'Jones'
-UNION
- SELECT S.SNO, S.SNAME, S.CITY
- FROM SUPPLIER S
- WHERE S.SNAME = 'Adams';
-
-
-gives the result:
-
-
- SNO | SNAME | CITY
------+-------+--------
- 2 | Jones | Paris
- 3 | Adams | Vienna
-
-
-
- Here is an example for INTERSECT:
-
-SELECT S.SNO, S.SNAME, S.CITY
- FROM SUPPLIER S
- WHERE S.SNO > 1
-INTERSECT
- SELECT S.SNO, S.SNAME, S.CITY
- FROM SUPPLIER S
- WHERE S.SNO < 3;
-
-
- gives the result:
-
-
- SNO | SNAME | CITY
------+-------+--------
- 2 | Jones | Paris
-
-
- The only tuple returned by both parts of the query is the one having SNO=2.
-
-
- Finally an example for EXCEPT:
-
-SELECT S.SNO, S.SNAME, S.CITY
- FROM SUPPLIER S
- WHERE S.SNO > 1
-EXCEPT
- SELECT S.SNO, S.SNAME, S.CITY
- FROM SUPPLIER S
- WHERE S.SNO > 3;
-
-
- gives the result:
-
-
- SNO | SNAME | CITY
------+-------+--------
- 2 | Jones | Paris
- 3 | Adams | Vienna
-
-
-
-
-
-
-
-
-
Data Definition
-
- There is a set of commands used for data definition included in the
-
-
-
-
Create Table
-
- The most fundamental command for data definition is the
- one that creates a new relation (a new table). The syntax of the
- CREATE TABLE command is:
-
-
-CREATE TABLE table_name
- (name_of_attr_1 type_of_attr_1
- [, name_of_attr_2 type_of_attr_2
- [, ...]]);
-
-
-
-
Table Creation
-
- To create the tables defined in
- the
- following
SQL statements are used:
-
-CREATE TABLE SUPPLIER
- (SNO INTEGER,
- SNAME VARCHAR(20),
- CITY VARCHAR(20));
-
-
-CREATE TABLE PART
- (PNO INTEGER,
- PNAME VARCHAR(20),
- PRICE DECIMAL(4 , 2));
-
-
-CREATE TABLE SELLS
- (SNO INTEGER,
- PNO INTEGER);
-
-
-
-
-
-
-
-
- The following is a list of some data types that are supported by
-
-
-
- INTEGER: signed fullword binary integer (31 bits precision).
-
-
-
-
- SMALLINT: signed halfword binary integer (15 bits precision).
-
-
-
-
- DECIMAL (p[,q]):
- signed packed decimal number of up to
- p
- digits, with
- q
- digits to the right of the decimal point.
- If q
- is omitted it is assumed to be 0.
-
-
-
-
- FLOAT: signed doubleword floating point number.
-
-
-
-
- VARCHAR(n):
- varying length character string of maximum length
- n.
-
-
-
-
- CHAR(n):
- fixed length character string of length
- n.
-
-
-
-
-
-
-
-
-
Create Index
-
- Indexes are used to speed up access to a relation. If a relation R
- has an index on attribute A then we can
- retrieve all tuples t
- having
- t(A) = a
- in time roughly proportional to the number of such
- tuples t
- rather than in time proportional to the size of R.
-
-
- To create an index in
SQL
- the CREATE INDEX command is used. The syntax is:
-
-CREATE INDEX index_name
- ON table_name ( name_of_attribute );
-
-
-
-
-
Create Index
-
- To create an index named I on attribute SNAME of relation SUPPLIER
- we use the following statement:
-
-CREATE INDEX I ON SUPPLIER (SNAME);
-
-
-
- The created index is maintained automatically, i.e., whenever a new
- tuple is inserted into the relation SUPPLIER the index I is
- adapted. Note that the only changes a user can perceive when an
- index is present are increased speed for SELECT
- and decreases in speed of updates.
-
-
-
-
-
-
-
Create View
-
- A view can be regarded as a virtual table,
- i.e., a table that
- does not physically exist in the database
- but looks to the user
- as if it does. By contrast, when we talk of a
- base table there is
- really a physically stored counterpart of each row of the table
- somewhere in the physical storage.
-
-
- Views do not have their own, physically separate, distinguishable
- stored data. Instead, the system stores the definition of the
- view (i.e., the rules about how to access physically stored base
- tables in order to materialize the view) somewhere in the system
- catalogs (see
- ). For a
- discussion on different techniques to implement views refer to
-
- SIM98.
-
-
- command is used to define a view. The syntax
- is:
-
-CREATE VIEW view_name
- AS select_stmt
-
-
- where select_stmt
- is a valid select statement as defined
- in .
- Note that select_stmt is
- not executed when the view is created. It is just stored in the
- system catalogs
- and is executed whenever a query against the view is made.
-
-
- Let the following view definition be given (we use
- the tables from
- again):
-
-CREATE VIEW London_Suppliers
- AS SELECT S.SNAME, P.PNAME
- FROM SUPPLIER S, PART P, SELLS SE
- WHERE S.SNO = SE.SNO AND
- P.PNO = SE.PNO AND
- S.CITY = 'London';
-
-
-
- Now we can use this virtual relation
- London_Suppliers as
- if it were another base table:
-
-SELECT * FROM London_Suppliers
- WHERE PNAME = 'Screw';
-
-
- which will return the following table:
-
-
- SNAME | PNAME
--------+-------
- Smith | Screw
-
-
-
- To calculate this result the database system has to do a
- hidden
- access to the base tables SUPPLIER, SELLS and PART first. It
- does so by executing the query given in the view definition against
- those base tables. After that the additional qualifications
- (given in the
- query against the view) can be applied to obtain the resulting
- table.
-
-
-
-
-
Drop Table, Drop Index, Drop View
-
- To destroy a table (including all tuples stored in that table) the
- DROP TABLE command is used:
-
-DROP TABLE table_name;
-
-
-
- To destroy the SUPPLIER table use the following statement:
-
-DROP TABLE SUPPLIER;
-
-
-
- The DROP INDEX command is used to destroy an index:
-
-DROP INDEX index_name;
-
-
-
- Finally to destroy a given view use the command DROP
- VIEW:
-
-DROP VIEW view_name;
-
-
-
-
-
-
-
Data Manipulation
-
-
-
Insert Into
-
- Once a table is created (see
- ), it can be filled
- with tuples using the command INSERT INTO.
- The syntax is:
-
-INSERT INTO table_name (name_of_attr_1
- [, name_of_attr_2 [, ...]])
- VALUES (val_attr_1 [, val_attr_2 [, ...]]);
-
-
-
- To insert the first tuple into the relation SUPPLIER (from
- ) we use the
- following statement:
-
-INSERT INTO SUPPLIER (SNO, SNAME, CITY)
- VALUES (1, 'Smith', 'London');
-
-
-
- To insert the first tuple into the relation SELLS we use:
-
-INSERT INTO SELLS (SNO, PNO)
- VALUES (1, 1);
-
-
-
-
-
-
Update
-
- To change one or more attribute values of tuples in a relation the
- UPDATE command is used. The syntax is:
-
-UPDATE table_name
- SET name_of_attr_1 = value_1
- [, ... [, name_of_attr_k = value_k]]
- WHERE condition;
-
-
-
- To change the value of attribute PRICE of the part 'Screw' in the
- relation PART we use:
-
-UPDATE PART
- SET PRICE = 15
- WHERE PNAME = 'Screw';
-
-
-
- The new value of attribute PRICE of the tuple whose name is 'Screw' is
- now 15.
-
-
-
-
-
Delete
-
- To delete a tuple from a particular table use the command DELETE
- FROM. The syntax is:
-
-DELETE FROM table_name
- WHERE condition;
-
-
-
- To delete the supplier called 'Smith' of the table SUPPLIER the
- following statement is used:
-
-DELETE FROM SUPPLIER
- WHERE SNAME = 'Smith';
-
-
-
-
-
-
-
System Catalogs
-
- In every
SQL database system
- system catalogs are used to keep
- track of which tables, views indexes etc. are defined in the
- database. These system catalogs can be queried as if they were normal
- relations. For example there is one catalog used for the definition of
- views. This catalog stores the query from the view definition. Whenever
- a query against a view is made, the system first gets the
- view definition query out of the catalog
- and materializes the view
- before proceeding with the user query (see
-
-
- for a more detailed
- description). For more information about system catalogs refer to
- .
-
-
-
-
-
- In this section we will sketch how
SQL can be
- embedded into a host language (e.g., C).
- There are two main reasons why we want to use
SQL
- from a host language:
-
-
-
- There are queries that cannot be formulated using pure
SQL
- (i.e., recursive queries). To be able to perform such queries we need a
- host language with a greater expressive power than
-
-
-
-
- We simply want to access a database from some application that
- is written in the host language (e.g., a ticket reservation system
- with a graphical user interface is written in C and the information
- about which tickets are still left is stored in a database that can be
- accessed using embedded
SQL).
-
-
-
-
-
- A program using embedded
SQL
- in a host language consists of statements
- of the host language and of
- (
ESQL) statements. Every
ESQL
- statement begins with the keywords EXEC SQL.
- The
ESQL statements are
- transformed to statements of the host language
- by a precompiler
- (which usually inserts
- calls to library routines that perform the various
SQL
- commands).
-
-
- When we look at the examples throughout
- we
- realize that the result of the queries is very often a set of
- tuples. Most host languages are not designed to operate on sets so we
- need a mechanism to access every single tuple of the set of tuples
- returned by a SELECT statement. This mechanism can be provided by
- declaring a cursor.
- After that we can use the FETCH command to
- retrieve a tuple and set the cursor to the next tuple.
-
-
- For a detailed discussion on embedded
SQL
- refer to
- ,
- ,
- or
- .
-
-
-
-