Académique Documents
Professionnel Documents
Culture Documents
capabilities offered by some of its more advanced implementations. One of the main differences between the
highly restricted Jet SQL behind Microsoft Access, and the more powerful Transact SQL used in Microsoft
SQL Server 7 and SQL Server 2000 is that, wherever you can use a table, you can usually also use a query,
a view, a union, or any type of JOIN statement. This is in stark contrast to Jet SQL where the use of sub
queries is very limited, and where there are many constraints placed on the order in which JOIN statements
are nested. As you proceed through the tutorial, you will see this point illustrated again and again in the
examples, and you will also find a few other tips and tricks that might be useful when implementing an
advanced database application.
Using Table And Field Aliases
Before proceeding to detail some of the features of Transact SQL, we shall quickly cover the use of aliases.
As advanced SQL queries can become quite complex, and the names of fields and tables quite lengthy, it is
often useful to be able to use aliases. Field aliases can be assigned using the following three methods:
alias = FieldName
FieldName AS alias
FieldName alias.
Table aliases, however, can only be assigned in two ways:
Table AS alias
Table alias.
For Example:
Simple UNIONS
The results of two queries on separate tables can be combined into a single, temporary table using a simple
UNION statement. Both queries must return the same number and type of columns, and field aliases can
only be applied to the first any applied to the second query are ignored. By default, a UNION will remove
duplicates, but this behavior can be overcome by using UNION ALL. Only a single ORDER BY clause can
be given at the end of the query.
Joining Tables
A simple INNER JOIN returns a temporary table consisting of all columns from the first table followed by all
columns from the second for those rows that are "matched" by the criteria of the ON clause. (These criteria
are not restricted to just simple tests for equality; they can be full Boolean expressions comparing multiple
values from both tables.) In the following example we select all the fields from the Delegate and
DelegateRegistration tables for every delegate who has a record in both.
SELECT *
FROM Delegate Del INNER JOIN DelegateRegistration DelReg
ON Del.DelegateID = DelReg.DelegateID
By switching to a LEFT JOIN, all rows from table 1 will appear in the result set, even if there is no "matching"
row in table 2 a NULL value being assigned to the relevant columns of those rows that were not matched.
Similarly, a RIGHT JOIN forces all rows in table 2 to show up in the results, even if there is no matching
record in table 1.
Finding The Difference Between Two TableSources
Using SQL's capability of joining two tables as described in the above section we are able to find records
that appear in one table but are absent from a second, related one. The standard technique for doing this is
to use a LEFT JOIN, and filter out those records that have no match.
Since you can use a tableexpression in exactly the same way as a table, you can also use a JOIN
statement to find the difference between a table and a query. The key thing to realize is that tables, JOIN
statements and queries are all tableexpressions, and as such can be treated like a table in every respect.
As the following example illustrates, a query can even be assigned a tablealias.
Using SubQueries
Subqueries can sometimes be used as an alternative to a JOIN statement to make the query more
readable. The syntax for a subquery is:
field operator [ANY|ALL] (query)
Here we retrieve all delegates that registered before May 14. The subquery returns the DelegateID's from
the DelegateRegistration table for all those delegates who registered before that date. Then this result set is
used as the criteria for selecting delegate information from the Delegate table.
UPDATE De l
SET Del.Status = RegType.DisplayName
FROM (Delegate Del INNER JOIN DelegateRegistration DelReg
ON Del.DelegateID = DelReg.DelegateID)
INNER JOIN RegistrationType RegType
ON DelReg.RegistrationTypeID = RegType.RegistrationTypeID
WHERE RegType.RegistrationTypeID = 2
A table row can only be updated with one record so, if the FROM clause returns more than one, then the first
record to match the criteria is used. Ideally, the FROM clause should only return one record for each row.
DELETE Statements
As with the UPDATE statement, the delete statement can also have a FROM clause to delete a record based
on the value of a related record in a second table. Here we delete all unregistered delegates.
DELETE Delegate
FROM Delegate LEFT JOIN DelegateRegistration
ON Delegate.DelegateID = DelegateRegistration.DelegateID
WHERE RegistrationTypeID IS NULL
Using The GROUP BY Clause
The GROUP BY clause is used to merge collections or groups of records into one. When a group of records
is collapsed in this way, we can specify aggregate functions to apply to the fields of the individual records to
give us summary values for the group. Only the summary values will be returned by the query all of the
data specific to the individual rows is lost. Each field in the SELECT list of a GROUP BY query must either
appear in the GROUP BY clause, or be used as the argument to an aggregate function. The available
aggregate functions are AVG, COUNT, MAX, MIN, SUM, STDDEV, STDDEVP, VAR, VARP. The following
example will return a temporary table with a row for each company containing its name and the number of its
delegates
Using The HAVING Clause
Just as a WHERE clause can be used to filter the individual rows that are returned by a standard query, so
the HAVING clause can be used to filter the group records that are returned by a GROUP BY query. The
following query returns all companies with more than one delegate.
Finding Duplicates
If we group records together by certain identifying fields we can then use a Count function to extract those
that are duplicated. This query utilizes a subquery and, based on their first and last names, returns a list of
DelegateIDs for those delegates that have duplicate records.
Removing Duplicates
The following query removes all duplicates from the delegate table, leaving only the originals of the
duplicated record. Here, we define a record as having a duplicate if there is another record with matching
FirstName and LastName fields. This query relies on a view being set up that returns a list of duplicate
delegates. The view is called DupDels.
Tricks With The IN Operator
The IN operator can be very useful when you wish to select records with field values that are equal to any
one of several possible literal values. Rather than having a series of comparisons linked together by OR
operators, a single IN clause can be used to compare a field's value against a list of possibilities as below:
A nice trick when building such a query string from an HTML multipleselect list, is to use the VBScript or
JavaScript Join function to merge all the selected values in the array into a commaseparated string. This
string can then be used directly as the argument to an operator in the database query.
Inserting Rows From A TableSource
In addition to insert statements for inserting a single record that take the following form:
INSERT INTO De lega te ( F i r s tName, Las tName, Sta tus , Company ID)
SELECT 'George', LastName, 'George', CompanyID
FROM George
A Note About Indexing
For queries to run efficiently it is important that appropriate indexes be in place. A simple guideline is that all
fields referenced in a comparison in a WHERE clause or in the ON clause of a JOIN statement should be
indexed. Bear in mind that all primary key fields are automatically indexed, but that foreign keys must have
an index added manually.
Well, there you have it. Now that you have witnessed some of the awesome power of SQL, with its greater
flexibility and increased capability, it is easy to see why it is the query language of choice for highend
database servers.