Sunteți pe pagina 1din 18

Search

Visual Basic 6 (VB6)


Home Tutorials

RSS: Site Feed

Introduction to SQL (Structured Query Language)

Twitter: Visual Basic


Facebook: Visual Basic

Navigate To

Level:

Written By TheVBProgramer.

Home

This tutorial is not directly related to Visual Basic 6. But you will use this information

Tutorials

heavily when writing any VB6 program that accesses a database. This teaches you all

Source Code Samples

the basics and then some of the SQL language - it does so using Access databases. The

VB.NET Tutorials
Add Your Tutorial
Forums
Articles
External Links
Advertise Here!
Contact Us

Guides
Beginner Guide
Controls Guide
Database Guide
Introduction to SQL
Using Data Control
Using DAO Code
Using RDO
Using ADO

SQL tutorial is pretty lengthy, but if you press through it you will really understand how
database programming works.

Prerequisites
This tutorial presumes that the reader has a working knowledge of
basic database table design principles, including basic
normalization and relationships (one-to-many, one-to-one, many-tomany). Once a database has been designed and its tables have
been populated with data, SQL can be used to manipulate the data
in those tables.
Tutorials on database normalization and relationships can be found
on various Internet sites. Even without this background, you may be
able to glean some of this knowledge by going through the
exercises in this tutorial.
You will need to have MS-Access 2000 (or higher) installed on your
system to perform the examples presented in this tutorial. For one of
the examples, you will also need MS-Excel.

ADO and ListView

About this Tutorial

ADO stored procs


Using Crystal Reports

User login
Username: *

Password: *

Log in
Create new account
Request new password

The sample database used for this tutorial is a modified version of


the sample "Northwind Traders" database, provided by Microsoft in
Visual Studio and MS-Office.
The original database provided by Microsoft ("NWIND.MDB")
contains many features that would detract from the purpose of this
tutorial (in that the purpose of this tutorial is teach you how to write
SQL to interact with database tables). The original database "shows
off" many features of an MS-Access database: it contains many
forms and reports; it also manipulates how some of the data
appears when you open a table to view its contents (for example, a
column may actually contain a numeric code, but the table
datasheet view is set up to show the description corresponding to
that code; also, in many cases a "display name" was set up for the
column for example, a column might actually be called
"CustName" but it would appear as "Customer Name" when you
opened the table).
The modified version of the database (called "NWINDVBP.MDB")
has stripped out all of the "extras" so that it contains only the tables,
and when you open a given table, you will see the true contents of
the columns in that table.
Download the "NWINDVBP.MDB" database here.
A Note on Terminology
In this tutorial, the term record will be used interchangeably with the
term row; and the term field will be used interchangeably with the
term column.

Introduction to SQL

SQL (Structured Query Language) is a language designed to


work with relational databases. Most people pronounce it "sequel",
although others insist it must be pronounced "ess cue ell". I believe
either pronunciation is fine.
In the mid 1970s, SQL was developed under the name SEQUEL
(for Structured English Query Language?) at the IBM San Jose
research facilities to be the data manipulation language for IBM's
prototype relational model DBMS called "System R". In 1980, the
language was renamed SQL to avoid confusion with an unrelated
hardware product called SEQUEL.
SQL is currently used (and has been for quite some time) as the
data manipulation language for most relational database
management products on the market today. This includes IBM's
DB2, Oracle, XBase (dBase, FoxPro, etc.), MS SQL Server, and
Access. Although there are various SQL "standards" (SQL-89, SQL92, etc.), there are variations in the "dialects" of SQL "spoken" by
the different vendors. For example, there are some things you can
do in Oracle SQL that you can't do with Access, and vice-versa.
On its own, SQL is a "non-procedural" language, meaning a
program is not typically written in "straight SQL". When used on its
own, a SQL command is given at a command-line interface
provided by the DBMS software. You can then view the results of
the single SQL command. Some DBMS's support SQL scripts (also
called "stored procedures"), which is a file containing multiple SQL
statements that are executed one after the other. SQL statements
can also be embedded in a "host" language (like VB, C, COBOL,
etc.), where a SQL statement can be executed and have its results
processed by the host language.
SQL accomplishes many powerful tasks with a mere seven
statements: SELECT, UPDATE, INSERT, DELETE, CREATE,
ALTER, and DROP. Each of these seven statements fall into one of
two categories: DML (Data Manipulation Language) statements or
DDL (Data Definition Language) statements. These statements are
summarized as follows:
DML Statements
SELECT Enables you to select one or more columns from one or
more tables in the database. The results can be
simply viewed, or can be used as the basis for a form
or report, or, in the case of embedded SQL, can be
processed as a temporary table (called a "recordset"
in Access, called a "cursor" in other DBMSs).
UPDATE Enables you to update the data in one or more columns of
one or more rows in a table.
INSERT Enables you to append rows to an existing table.
DELETE Enables you to delete one or more rows from an existing
table.

DDL Statements

CREATE Enables you to create a new table, or to create a new


index on an existing table.
ALTER Enables you to modify the structure of an existing table (by
adding or deleting columns).
DROP Enables you to delete a table

The Northwind Traders Database

This tutorial uses the database for Northwind Traders, a fictional


company that is a distributor of specialty food items. The link to
download the database file, NWINDVBP.MDB, is provided above.
The Northwind Traders database consists of eight tables, as shown
below (to view this in Access, go to Tools Relationships):

How to do Command-line SQL in Access

Open the database that you want to work with (in this case,
NWINDVBP.MDB).

Select Queries from the Objects sidebar, then click New:

The New Query dialog box appears (with "Design View" preselected as the default). Click OK:

The Show Table dialog box appears (note: your list of table
names will not initially contain all of the table names shown
here). Click Close:

The leftmost button on the Access toolbar should say "SQL".


Click that button:

A text-entry box will appear (with the word "SELECT" preentered and highlighted). This is where you type your SQL
query:

Try one now. Type the following in the text-entry box:


SELECT CustomerID, CompanyName, ContactName
FROM Customers

Note: SQL is NOT case-sensitive. You can enter keywords, table


names, and field names in either upper- or lower-case letters
(or a combination of the two). The only time case-sensitivity
is an issue is when you are dealing with quoted strings.

To run the query, click the Run button on the toolbar (it's the
"exclamation point" icon):

Access then displays the results of the query in a datasheet


view:

To return to SQL view, select that option from the drop-down


list of the leftmost toolbar icon:

Once you have returned to SQL view, you can overwrite the SQL
command that you entered with the next SQL query you wish to
enter. Before you overwrite the existing query, you can save it, as
explained below.

FYI: To see the graphical representation of the SQL query that


you entered, select the "Design View" option :

Whenever you write a query in SQL, Access builds the graphical


representation of that query (if possible) behind the scenes (certain
types of SQL queries cannot be represented graphically).
Conversely, whenever you build a query graphically, Access
generates the equivalent SQL statement behind the scenes.
Saving Queries
To save a query in the Access database, click the Save button (the
diskette icon) on the Access toolbar. This will enable you to recall
the query from the Queries tab in Access.
If you wish to only save the SQL statement (but not save the query
in Access), you can select the text you entered in SQL view, copy it,
then paste it into another application (such as Notepad, Word, or the
VB code editor). Conversely, you can type up a SQL query in

Notepad or Word, copy it, then paste it into the SQL View text-entry
screen.
When you are at the point where you are writing a VB application
that requires embedded SQL statements, you can use the graphical
query capabilities of Access to "cheat". For example, if you can't
recall exactly how to phrase a particular SQL statement, you can
build a test query in Access with the graphical designer and run it. If
it produces the desired results, you can switch over to SQL View
and "steal" the code (i.e., copy it from Access and paste into VB).
However there is no substitute for simply "knowing" how to get
the job done and you may need to work with a DBMS that does
not have a graphical designer for queries.
For each example in the following tutorial, please key in and run the
SQL commands as shown. The SQL commands to key in will be
shown in bold Courier, like the following:
SELECT CustomerID, CompanyName, ContactName
FROM Customers
The expected results of each query will also be shown, so that you
can compare them to your results.

Part I: Single-Table Queries

The Basic SELECT Query


The SELECT query retrieves one or more columns (fields) from a
table. The basic syntax is:
SELECT field1 [, field2, ... fieldn] FROM tablename
Notes: If more than one field is specified, each field must be
separated with a comma. If you want to select ALL fields from a
table, you can use an asterisk (*) instead of a list of all the fields.
Example 1:
Retrieve all columns and all rows from the Employees table.
SELECT * FROM EMPLOPYEES

Example 2:
Retrieve the Product ID, product name, and unit price from all rows
of the Products table:
SELECT ProductID, ProductName, UnitPrice
FROM Products

Note: SQL statements can be entered on multiple


lines, as in the query above. A recommended
practice is to start each clause of the SQL
statement on a separate line. This is a style
consideration only; it has no effect on the
interpretation of the statement.
Adding a WHERE Clause
By adding an appropriate WHERE clause to a SELECT statement,
you can limit the number of rows (records) returned by the query.
The WHERE clause specifies a condition that must be met in order
for that row be returned.
Note: In the WHERE clause, numeric literals have no delimiters,
string literals are delimited by single quotes (') (although Access will
also accept double quotes(")), and date delimiters are delimited by
the number sign (#). Delimiting dates with the number sign is
specific to Access; most other DBMS' use the single quote as the
date delimiter.
Example 3:
What is the name for product ID 19?
SELECT ProductName
FROM Products
WHERE ProductID = 19

Example 4:
Which customers are from Mexico? (Show Customer ID, company
name, contact name, and contact title in the results.)
SELECT CustomerID, CompanyName,
ContactName, ContactTitle
FROM Customers
WHERE Country = 'Mexico'

Example 5:
Which employees were hired on October 17, 1993? (Show
employee first and last name, and title in the results.)
SELECT FirstName, LastName, Title
FROM Employees
WHERE HireDate = #10/17/1993#

Compound Conditions (Using AND and OR)


Example 6:
Which meat/poultry products (CategoryID = 6) have less than 10
units in stock? (Show product ID, product name, category ID, and
units in stock in the results.)
SELECT ProductID, ProductName,
CategoryID, UnitsInStock
FROM Products
WHERE CategoryID = 6 AND UnitsInStock
< 10

Example 7:
Which items in the Product table are classified as meat/poultry or
have less than 10 units in stock? (Show product ID, product name,
category ID, and units in stock in the results.)
SELECT ProductID, ProductName,
CategoryID, UnitsInStock
FROM Products
WHERE CategoryID = 6 OR UnitsInStock <
10

You can join multiple conditions using AND and OR. When both
AND and OR are used in the WHERE clause, "AND" takes
precedence. This precedence can be overridden by using
parentheses. Examples 8 and 9 illustrate this:
Example 8:
Show the product name, units in stock, category ID, and unit price
for seafood products (category ID = 8) that have at least 100 units in
stock, or for any item whose unit price is greater than $50.
SELECT ProductName, UnitsInStock,

CategoryID, UnitPrice
FROM Products
WHERE UnitsInStock >= 100
AND CategoryID = 8
OR UnitPrice > 50

Example 9:
Show the part product name, units in stock, category ID, and unit
price for products that have at least 100 units in stock, and that are
either classified as seafood (category ID = 8) or have a unit price
greater than $50.
SELECT ProductName, UnitsInStock,
CategoryID, UnitPrice
FROM Products
WHERE UnitsInStock >= 100
AND (CategoryID = 8
OR UnitPrice > 50)

Using NOT
Example 10:
Show the company name, contact name, and country for all non-US
suppliers.
SELECT CompanyName, ContactName,
Country
FROM Suppliers
WHERE NOT (Country = 'USA')

Note: This query could also be coded as:


SELECT CompanyName, ContactName,
Country
FROM Suppliers
WHERE Country <> 'USA'
Some DBMS' use "!=" for "not equal to" in addition to or instead of
"<>".
Using BETWEEN / AND
Example 11:
Show the Product ID, product name, and unit price for all products
that have a unit price between $10 and $15
(inclusive):
SELECT ProductID, ProductName,
UnitPrice
FROM Products
WHERE UnitPrice BETWEEN 10 AND 15

Note: This query could also be coded as:


SELECT ProductID, ProductName,
UnitPrice
FROM Products
WHERE UnitPrice >= 10 AND UnitPrice <=
15
Example 12:
Show the Order ID, Customer ID, and order date for orders that
occurred between February 1 and February 7, 1995.
SELECT OrderID, CustomerID, OrderDate
FROM Orders
WHERE OrderDate BETWEEN #2/1/1995# AND
#2/7/1995#

Reminder: In Access SQL, Date literals must be delimited by pound


signs (#). In most other database systems, dates are
delimited with single quotes (same as strings).
Also: Queries based on dates become slighltly more involved if the
dates have a time component to them (the dates in this
database do not have a time component, but they
could, because Date/Time fields can store both date
and time together). If the OrderDate field contained a
time component, you would have to write the WHERE
clause of the above query like this:
WHERE OrderDate BETWEEN
#2/1/1995# AND #2/7/1995 11:59:59PM#
- or WHERE OrderDate >= #2/1/1995# AND
OrderDate < #2/8/1995#

Using Computed Columns (Expressions)


In the list of fields to be selected, you can specify an expression
(arithmetic or string) that consists of a combination of fields and/or
literals. In Access SQL, an expression can also incorporate a VB
function such as DateAdd, Format$, Left$, etc. (although such
expressions would not be accepted in non-Access environments,
such as Oracle or SQL Server however, those other DBMS
environments have their own vendor-specific functions that can be
used in expressions).
Example 13:
Show the OrderID, ProductID, UnitPrice, Quantity, Discount, and
line item total for order line items that total at least
$300.
SELECT OrderID, ProductID, UnitPrice,
Quantity, Discount, Format$(UnitPrice
* Quantity * (1 + Discount), "Fixed")
FROM [Order Details]
WHERE (UnitPrice * Quantity * (1 +
Discount)) >= 300

Note that Access generates a default name for computed columns


in the form Expr####. You can override this default
name by using an alias for the column name via the
AS clause (see the next example).
Note also that the table "Order Details" has an embedded space in
its name. Although this is not good practice, Access
will allow it for all of its objects (tables, columns,
queries, etc.). When an object name contains
embedded spaces (and other odd characters), you
must enclose it square brackets as was done in the
example above.
Example 14:
Repeat Example 13, except call the computed column
"LineItemTot".
SELECT OrderID, ProductID, UnitPrice,
Quantity, Discount,
Format$(UnitPrice * Quantity * (1 +
Discount), "Fixed") AS LineItemTot
FROM [Order Details]
WHERE (UnitPrice * Quantity * (1 +
Discount)) >= 300

Note: Some database systems do not require the word AS to specify


an alias (in those systems, the expression is separated from the
alias name with just a blank space).
Using LIKE
A WHERE clause condition can use the pattern-matching
capabilities of the LIKE operator. In Access SQL, the syntax for LIKE
is identical the VB syntax. In other database systems, the syntax for
LIKE may vary (for example, Oracle uses a percent sign (%) instead
of an asterisk (*) for a wildcard character).
Example 15:
Show company name, contact name, and title for customers whose
contact person is considered a "manager".
SELECT CompanyName, ContactName,
ContactTitle
FROM Customers
WHERE ContactTitle LIKE '*Manager*'

Using IN
The IN operator can be used in a WHERE clause condition to
specify that a field must be equal to any of several values.
Example 16:
Show company name and address information for all suppliers
located in France, Germany, and Italy.
SELECT CompanyName, Address, City, Country,
PostalCode
FROM Suppliers
WHERE Country IN ('France', 'Germany', 'Italy')

Note: This query could also be coded as:


SELECT CompanyName, Address, City, Country,
PostalCode
FROM Suppliers
WHERE Country = 'France'
OR Country = 'Germany'
OR Country = 'Italy'

(As you can see, using IN in this case is much more


concise.)
Sorting with the ORDER BY clause
You can sort the results of your query on any field or fields by using
an ORDER BY clause.
Example 17-a:
Show the category ID, unit price, and product name for all products,
sorted by unit price (low to high).
SELECT CategoryID, UnitPrice,
ProductName
FROM Products
ORDER BY UnitPrice

Note: By default, ORDER BY sorts the data in ascending


(low to high) sequence. You can specify an ascending or
descending sort by using the keywords ASC or DESC,
respectively. The last line of the above query could have
been written:
ORDER BY UnitPrice ASC
Example 17-b:
Show the category ID, unit price, and product name for all products,
sorted by unit price (high to low).
SELECT CategoryID, UnitPrice,
ProductName
FROM Products
ORDER BY UnitPrice DESC

Example 18:
Show the category ID, unit price, and product name for all products,
sorted by unit price (high to low) WITHIN category ID.
SELECT CategoryID, UnitPrice, ProductName
FROM Products
ORDER BY CategoryID, UnitPrice DESC

Using SQL Functions


The COUNT Function
The COUNT function in a SELECT statement returns a count of the
number of records in a table (if the statement has a WHERE clause,
it returns only the number of records that meet the specified
condition).
The syntax for the COUNT function requires that the word COUNT
be followed by a field name in parentheses; normally, you would
place an asterisk between the parentheses to signify "any field":
COUNT(*). The COUNT function counts records; it is not dependent
on any particular field within a record.
Some database systems do not support the asterisk syntax on the
COUNT function; on those systems the syntax COUNT(fieldname)
must be used, and any field name would do.
Example 19:
How many products are classified as beverages (category ID 1)?
SELECT COUNT(*) AS BeverageCount
FROM Products
WHERE CategoryID = 1

The SUM Function


The SUM function in a SELECT statement returns the sum of a
numeric field or expression for all of records in a table (if the
statement has a WHERE clause, it sums that field only for the
records that meet the specified condition).
Example 20:
How many order lines do we have, and what is their total value?
SELECT COUNT(*) AS OrderLineCount,
SUM(UnitPrice * Quantity * (1 +
Discount)) AS OrderLineTotal
FROM [Order Details]

Note: If you wanted to format the total, you could wrap the Format$
function around the SUM expression as follows:
SELECT COUNT(*) AS OrderLineCount,
Format$(SUM(UnitPrice * Quantity * (1
+ Discount)), "Currency") AS
OrderLineTotal
FROM [Order Details]

The AVG, MAX, and MIN Functions


An AVG, MAX, or MIN function in a SELECT statement returns the
average value, maximum value, or minimum value, respectively, of
a numeric field for all of records in a table (if the statement has a
WHERE clause, the function is performed for that field only for the
records that meet the specified condition).
Example 21:
Display the total order line value, average order line value, highest
order line value, and lowest order line value.
SELECT Format$(SUM(UnitPrice * Quantity * (1 +
Discount)), "Currency") AS OrderLineTotal,
Format$(AVG(UnitPrice * Quantity * (1 + Discount)),
"Currency") AS AverageOrderLine,
Format$(MAX(UnitPrice * Quantity * (1 + Discount)),
"Currency") AS HighestOrderLine,
Format$(MIN(UnitPrice * Quantity * (1 + Discount)),
"Currency") AS LowestOrderLine
FROM [Order Details]

Using DISTINCT
Example 22-a:
As a verification, run the query below to see that any particular
customer may have more than one order in the Orders table:
SELECT * FROM Orders ORDER BY CustomerID

Example 22-b:
Use the DISTINCT keyword to show each customer in the
ORDERS table only once.
SELECT DISTINCT CustomerID FROM Orders

STOP. Do not get rid of the above query; we're going to save it shortly.
Now a problem is going to present itself. Suppose you are asked "how many
customers have orders?" In Oracle and other DBMS' (but not Access), DISTINCT
can be used as a function, which would enable you to satisfy this question using
one query, like so:

SELECT COUNT(DISTINCT(CustomerID)) FROM Orders


Oracle would return the correct results, but attempting the above in Access would
result in an error. What to do?

Sometimes it is necessary to run more than one query, back-toback, to solve a particular problem (for example, the results of the
first query would be used to "feed" the second query). This is
exactly what we must do to answer the question "how many
customers have orders?". Save the query you wrote in example 22b as qryDistinctCust.
When you save a query, only the query definition is saved (when
the query is run for the first time, it is compiled as well) the
output results of the query are not saved; they are recreated every
time the query is run. FYI: In Access, saved queries are known as
"QueryDefs" (at least, programmers call them that). In other
database systems, saved queries may be called "views" or "stored
procedures".
The "Make Table" (SELECT / INTO) Query
It is also possible to make a query that saves its results to a new
table. Access calls this a "make table" query, and it is accomplished
in SQL by using the INTO clause of the SELECT statement. (Note:
Not all versions of SQL support SELECT / INTO).
Example 22-c:
The following query will save its results to a table named
tblCustsWithOrders:
SELECT DISTINCT CustomerID AS CustNbr
INTO tblCustsWithOrders
FROM Orders
Access may warn you that this will create a permanent
table and that you can't undo this action. If so, click OK
and let Access do its thing. If you check the Tables tab
in Access, you'll see that this table is now there.

You can check the results by either opening the table


or by running the following query:
SELECT * FROM tblCustsWithOrders

To get a count of the number of unique customers in the ORDERS


table, we can use the COUNT function on either the newly created
query or on the newly created table.
Example 22-d:
Get a count of the number of unique customers in the ORDERS
table by using the COUNT function on the saved qryDistinctCust
query (note that Access allows you to use a saved query (QueryDef)
in place of a table name in a SELECT query).
SELECT COUNT(*) AS CustCount FROM
qryDistinctCust

Example 22-e:
Get a count of the number of unique customers in the ORDERS
table by using the COUNT function on the new
tblCustsWithOrders table.
SELECT COUNT(*) AS CustCount FROM
tblCustsWithOrders

Subqueries
On the right-hand side of a conditional expression in a WHERE
clause, you can use a subquery to return a comparison value. The
subquery, which must return only one column, is executed first. The
result of the subquery is then incorporated into the main query. If the
subquery can only return a single value (one row, one column), then
a relational operator (like = or >) can be used, as in the next two
examples.
Example 23:
Show all fields of Order table for orders that were placed on the
most recent order date.
SELECT *
FROM Orders
WHERE OrderDate = (SELECT
MAX(OrderDate) FROM Orders)

The above query works as follows: the subquery


SELECT MAX(OrderDate) FROM Orders
will execute and return one value (the date 6/5/1996). You can verify
that result by looking at the Order table you'll see
that the latest date for any order is 6/5/1996. That
result (6/5/1996) is then used as the comparison value
in the outer WHERE clause, effectively making it read:
WHERE OrderDate = #6/5/1996#"
Note: The dates in this table do not have a time component to them.
If they did, the query would have to do a little more
work to specify the desired date.
Example 24:
Show the OrderID, ProductID, UnitPrice, Quantity, Discount, and
line item total for order lines that exceed the average
order line total.
SELECT OrderID, ProductID, UnitPrice,
Quantity, Discount,
Format$(UnitPrice * Quantity * (1 +
Discount), "Fixed") AS OrderLineTotal
FROM [Order Details]
WHERE (UnitPrice * Quantity * (1 +
Discount)) > (SELECT AVG(UnitPrice *
Quantity * (1 + Discount))
FROM [Order Details])

The above query works as follows: the subquery


SELECT AVG(UnitPrice * Quantity * (1 +
Discount)) FROM [Order Details]
will execute and return one value ($669.66). You can verify that by
looking at the results of example 21. That result
($669.66) is then used as the comparison value in the
outer WHERE clause, effectively making it read:
WHERE (UnitPrice * Quantity * (1 + Discount)) >
669.66
If the subquery can return multiple values (multiple rows, one
column each), then the keyword IN must be used instead of a
relational operator. This type of query is typically used in multi-table
queries, which are presented in Part II of this document. The next
example is a "sneak preview" of a multi-table query that uses a
subquery that returns multiple values.
Example 25:
Show the orders will be shipped by either Speedy Express or
Federal Shipping.
SELECT *
FROM Orders
WHERE ShipVia
IN (SELECT ShipperID FROM Shippers
WHERE CompanyName IN ('Speedy
Express', 'Federal Shipping'))

The above query works as follows: the subquery


SELECT ShipperID FROM Shippers WHERE CompanyName
IN ('Speedy Express', 'Federal
Shipping')
will execute and return a result set consisting of two rows (one row
containing the ShipperID for Speedy Express, the
other containing the ShipperID for Federal Shipping).
This result set will then supply the values to the IN
clause, as if the query was written as follows:
SELECT *
FROM Orders
WHERE ShipVia IN (1, 3)
Grouping Data with the GROUP BY Clause
When you group data, you create a query that produces one record
for each unique value of a field (or combination of fields) in a table
(limited by the WHERE clause, if there is one). Any of the SQL
functions discussed earlier (COUNT, SUM, AVG, etc.) apply to the
grouped record.
Example 26:
Show the order ID and order total for each order.
SELECT OrderID, SUM(UnitPrice * Quantity * (1 +

Discount)) AS OrderTotal
FROM [Order Details]
GROUP BY OrderID

Using the HAVING clause


Just as the WHERE clause can be used to limit the rows that are
included in the result of a SQL command, the HAVING clause can
be used to limit the groups that are included.
Example 27:
Show the order number and order total for each order, but include
only orders that have a total greater than $1000.
SELECT OrderID, SUM(UnitPrice * Quantity * (1 +
Discount)) AS OrderTotal
FROM [Order Details]
GROUP BY OrderID
HAVING SUM(UnitPrice * Quantity * (1 +
Discount)) > 1000

FYI: Even when you use an alias for a computed column, you must
still use the expression, not the alias, in the HAVING
clause (this also applies to the WHERE and ORDER
BY clauses if a computed column is used with
either of these, it is the expression, not the alias, that
must be specified.)
Example 28:
For each order, show the number of order lines that make up that
order.
SELECT OrderID, Count(*) AS OrderLineCount
FROM [Order Details]
GROUP BY OrderID

Example 29:
For each order, show the number of order lines that make up that
order; but only include orders containing three or more
items.
SELECT OrderID, Count(*) AS OrderLineCount
FROM [Order Details]
GROUP BY OrderID
HAVING Count(*) >= 3

Example 30:
For each order, show the number of order lines that make up that
order, but only for orders that include product IDs 4 or 5 (a "Chef
Anton" product).
SELECT OrderID, Count(*) AS OrderLineCount
FROM [Order Details]
WHERE OrderID IN (SELECT OrderID FROM [Order
Details] WHERE ProductID IN (4,5))
GROUP BY OrderID

In this example, the SQL interpreter must perform two "passes" behind the scenes. First it
applies the WHERE clause to the table. From that resulting set of records, the grouping is
performed.

Example 31:
For each order, show the number of order lines that make up that
order, but only for orders that include product IDs 4 or 5 (a "Chef
Anton" product) and that have at least three or more total items.
SELECT OrderID, Count(*) AS OrderLineCount
FROM [Order Details]
WHERE OrderID IN (SELECT OrderID FROM [Order Details] WHERE
ProductID IN (4,5))
GROUP BY OrderID
HAVING Count(*) >= 3

As in the previous example, the SQL interpreter must perform a number of passes
behind the scenes. First it applies the WHERE clause to the table. From that resulting set
of records, the grouping is performed. From the grouped set of records, the HAVING
clause is then applied.

Part II: Multiple-Table Queries (Joins)

One of the results of normalizing your tables is that most queries will
draw on several tables in order to get the desired result. As a result,
most of the queries you create will need to combine two or more
tables. In Access SQL, tables are joined by specifying which fields
of the tables you want to match on, either in a WHERE clause or in
a JOIN clause.
Let's do an example first, then resume with a further explanation of
how the join works.
Example 32-a:
List the order ID and product name for each order line on the Order
Details table.
SELECT OrderID, ProductName
FROM [Order Details], Products
WHERE [Order Details].ProductID =
Products.ProductID
ORDER BY OrderID

In the syntax for the above query, note the following:

Since we needed to draw from both the Order Details table


and the Products table, both of those tables were specified in
the FROM clause, separated by a comma.

When you join two or more tables and those tables share
common field names, those field names must be qualified in the
query this is the case in the query above for the ProductID
field (both the Order Details and Products tables have a field
with that names). To qualify a field name, use the syntax
tablename.fieldname.

To specify how the tables should be joined, a WHERE clause


is used to specify a matching (equal) condition between the
fields that link the two tables (usually, these are the fields that
were involved in establishing a one-to-many relationship
between the two tables).

To understand why the query works the way it does, let's explore a
little relational database theory:

The relational model specifies that the first step in creating a


join is to generate the Cartesian product of the two tables. The
Cartesian product for two tables is another (virtual) table
contains records made up of every possible combination of
records from the two joined tables. In the case of the Order
Details and Products tables, the Cartesian product would be a
virtual table of 165935 records (2155 Order Details records X 77
Products records): i.e., the data for each and every Products row
would be joined with each and every Order Details row.

From the Cartesian product, the records meeting the WHERE


clause are extracted (thus, only records where the ProductID
field matches are selected).

From the matched records, the desired columns (as specified


in the SELECT clause) are extracted, resulting in the final result
set.

To reduce the amount of typing required by qualifying the field


names with the table names, you can use a short alias on the table
names with the AS clause, as in the following example:
Example 32-b:
Modify the query in 32-a to use table name aliases:
SELECT OrderID, ProductName
FROM [Order Details] AS OD, Products
AS P
WHERE OD.ProductID = P.ProductID
ORDER BY OrderID
The above will produce the same results as example
32-a.
Note: Some database systems do not require (and some will not
allow) the word AS to specify an alias (in those
systems, the table name is separated from the alias
name with just a blank space).
Using INNER JOIN

As an alternative to specifying the join criteria in the WHERE clause, Access SQL
allows you to specify the join criteria with the INNER JOIN clause, which is part of
the FROM clause. The basic syntax is:
SELECT fields
FROM table1 INNER JOIN table2 ON table1.field = table2.field
The INNER JOIN syntax is not supported on all database systems, but it is on
most (including SQL Server and more recent versions of Oracle).

Example 32-c:
List the order ID and product name for each order line on the Order
Details table. Use the INNER JOIN clause to specify the join
criteria.
SELECT OrderID, ProductName
FROM [Order Details] AS OD INNER JOIN
Products AS P ON OD.ProductID =
P.ProductID
ORDER BY OrderID
The above will produce the same results as examples
32-a and 32-b.

WHERE vs. INNER JOIN

On the one hand, specifying join criteria with the WHERE clause is
universally acceptable on all database systems that use SQL. On
the other hand, INNER JOIN is preferred in Access SQL, because
this format makes the join criteria explicit, rather than inferring it from
the WHERE clause the WHERE clause is then reserved for
selection criteria, rather than doing dual-duty as a join specifier.
Future examples in this tutorial will show joins using both formats.
Example 33:
List the order ID, customer ID, and order date together with the sales
rep first name and last name for the sales rep who made the order
for all orders made in the month of September, 1994.
SELECT OrderID, CustomerID, OrderDate,
FirstName, LastName
FROM Orders AS O, Employees AS E
WHERE O.EmployeeID = E.EmployeeID
AND OrderDate BETWEEN #9/1/1994# AND
#9/30/1994#
ORDER BY OrderID
-- or SELECT OrderID, CustomerID, OrderDate,
FirstName, LastName
FROM Orders AS O INNER JOIN Employees
AS E ON O.EmployeeID = E.EmployeeID
WHERE OrderDate BETWEEN #9/1/1994# AND
#9/30/1994#
ORDER BY OrderID

In addition to joining tables with the WHERE clause or INNER JOIN


clause, you can also join tables by using IN with a subquery. The
next example illustrates this.
Example 34:
Find the description for every product included in order number
10250.
SELECT ProductName
FROM [Order Details] AS OD, Products
AS P
WHERE OD.ProductID = P.ProductID
AND OD.OrderID = 10250
-- or -SELECT ProductName
FROM [Order Details] AS OD INNER JOIN
Products AS P ON OD.ProductID =
P.ProductID
WHERE OD.OrderID = 10250
-- or -SELECT ProductName
FROM Products
WHERE ProductID IN (SELECT ProductID
FROM [Order Details] WHERE OrderID =
10250)

The next example joins three tables together and shows three
different ways to get the results (joining with WHERE, INNER JOIN,
or nested subquery):
Example 35:
Find the order ID and order date for every order that includes a
product with "Chef Anton" in the product name.
SELECT DISTINCT O.OrderID, OrderDate
FROM Orders AS O, [Order Details] AS
OD, Products AS P

WHERE O.OrderID = OD.OrderID


AND OD.ProductID = P.ProductID
AND P.ProductName LIKE '*Chef Anton*'
-- or -SELECT DISTINCT O.OrderID, OrderDate
FROM (Orders AS O INNER JOIN [Order
Details] AS OD ON O.OrderID =
OD.OrderID)
INNER JOIN Products AS P ON
OD.ProductID = P.ProductID
WHERE P.ProductName LIKE '*Chef
Anton*'
-- or -SELECT DISTINCT O.OrderID, OrderDate
FROM Orders AS O
WHERE OrderID IN (SELECT OrderID
FROM [Order Details]
WHERE ProductID IN (SELECT ProductID
FROM Products
WHERE ProductName LIKE '*Chef
Anton*'))

Note: The DISTINCT keyword was used because if a particular order contained
more than one "Chef Anton" product, that OrderID would be
duplicated in the resultset. We only want to see the unique
OrderIDs (and their dates) for all orders that have one or more
Chef Anton products.
Comprehensive Example

Example 36:
This query incorporates most of the major SQL clauses discussed
so far. This query joins four tables together to show the Order ID,
order date, customer (company name), employee name and order
total for all orders made in the month of January 1995 that totalled
$1500 or more.
SELECT O.OrderID, O.OrderDate,
C.CompanyName, E.FirstName,
E.LastName,
SUM(OD.UnitPrice * OD.Quantity * (1 +
OD.Discount)) AS OrderTotal
FROM Orders AS O, [Order Details] AS
OD, Customers AS C, Employees AS E
WHERE O.OrderID = OD.OrderID
AND O.CustomerID = C.CustomerID
AND O.EmployeeID = E.EmployeeID
AND O.OrderDate BETWEEN #1/1/1995# AND
#1/31/1995#
GROUP BY O.OrderID, O.OrderDate,
C.CompanyName, E.FirstName, E.LastName
HAVING SUM(OD.UnitPrice * OD.Quantity
* (1 + OD.Discount)) >= 1500
-- or -SELECT O.OrderID, O.OrderDate,
C.CompanyName, E.FirstName,
E.LastName,
SUM(OD.UnitPrice * OD.Quantity * (1 +
OD.Discount)) AS OrderTotal
FROM ((Orders AS O INNER JOIN [Order
Details] AS OD ON O.OrderID =
OD.OrderID)
INNER JOIN Customers AS C ON
O.CustomerID = C.CustomerID)
INNER JOIN Employees AS E ON
O.EmployeeID = E.EmployeeID
WHERE O.OrderDate BETWEEN #1/1/1995#
AND #1/31/1995#
GROUP BY O.OrderID, O.OrderDate,
C.CompanyName, E.FirstName, E.LastName
HAVING SUM(OD.UnitPrice * OD.Quantity
* (1 + OD.Discount)) >= 1500

Outer Joins

The INNER JOIN retrieves records only when there is a match in


both tables. In some cases, you may want to retrieve the values from
one table even when there are no matching values in the other
joined table. For example, suppose you wanted a list of all
employees showing the orders that they placed in a given week (if
any). To accomplish this, you could perform an outer join between
the Employees table and the Orders table.
Instead of using the keywords "INNER JOIN", you use "LEFT
OUTER JOIN" or "RIGHT OUTER JOIN" (the keyword "OUTER" is
optional; the keyword "LEFT" or "RIGHT" implies an outer join; in
fact, in some DBMS', the keyword OUTER is not allowed).
Example 37:
List the employee first name and employee last name for all
employees, together with the order IDs and order dates for orders
made by that employee (if any) for the week of September 26
through September 30, 1994. (If an employee made more than one
order during that time period, that employee will show up more than
once.)
Note: In order for this query to produce the desired results, a table
expression (sometimes called an in-line view or in-line table) is
used as the second table being joined in the SQL statement. In
many cases, most DBMS' will allow a table expression to be used
where a table name is expected. The table expression SELECT *
FROM Orders WHERE OrderDate BETWEEN #9/26/1994# AND
#9/30/1994# specifies a subset of records from the Orders table for
the desired date range.
SELECT E.FirstName, E.LastName,
O.OrderID, O.OrderDate
FROM Employees AS E
LEFT JOIN (SELECT * FROM Orders WHERE
OrderDate BETWEEN #9/26/1994# AND
#9/30/1994#) AS O
ON E.EmployeeID = O.EmployeeID

In the results above, for employees that don't have orders, the
OrderID and OrderDate columns will contain NULL. This fact
can be used in the type of query that asks the question,
"which employees do NOT have orders?":
Example 38:
List the employee first name and employee last name for all
employees for that had no orders for the week of September 26
through September 30, 1994.
SELECT E.FirstName, E.LastName,
O.OrderID, O.OrderDate
FROM Employees AS E
LEFT JOIN (SELECT * FROM Orders WHERE
OrderDate BETWEEN #9/26/1994# AND
#9/30/1994#) AS O
ON E.EmployeeID = O.EmployeeID
WHERE O.OrderID IS NULL

Self-Joins

It is possible to create a join between a table and a second instance


of the same table. A common example is an Employees table in
which the "ReportsTo" field (i.e., the employee's supervisor)
contains EmployeeID values found in the Employees table itself.
The following example joins the Employees table to itself. The
ReportsTo field in the first instance of the table is linked to the
EmployeeID field in the second instance.
Example 39-a:
List the employee ID, last name, and first name for each employee,
together with the last name and first name of that employee's
supervisor.

SELECT E1.EmployeeID, E1.LastName,


E1.FirstName,
E2.LastName, E2.FirstName
FROM Employees AS E1 INNER JOIN
Employees AS E2
ON E1.ReportsTo = E2.EmployeeID

Because an inner join was specified, if the value in the ReportsTo


field of any given record isn't also found in the EmployeeID field, the
record isn't selected. This would leave out records where the
ReportsTo field is NULL, perhaps indicating that the employee is a
supervisor and doesn't report to another employee in the
Employees table (as is the case for Andrew Fuller).
Example 39-b:
Revise the query written in exercise 41-a to use a LEFT JOIN, so
that all employee records will be selected, whether or not they have
a supervisor:
SELECT E1.EmployeeID, E1.LastName,
E1.FirstName,
E2.LastName, E2.FirstName
FROM Employees AS E1 LEFT JOIN
Employees AS E2
ON E1.ReportsTo = E2.EmployeeID

UNION Queries

A union query is one which creates a result set consisting of the


results of two or more queries appended to one another with any
duplicates removed.
Example 40:
List the employee first name and employee last name for employees
that either placed orders on the week of September 26 through
September 30, 1994, or employees that ever had an order
containing a Chef Anton product (product IDs 4 or 5), or both.
Include in the listing a column indicating which of these conditions
was met.
SELECT FirstName, LastName, 'Had orders week of
9/26' AS ConditionMet
FROM Employees AS E INNER JOIN Orders AS O ON
E.EmployeeID = O.EmployeeID
WHERE OrderDate BETWEEN #9/26/1994# AND
#9/30/1994#
UNION
SELECT FirstName, LastName, 'Sold Chef Anton'
FROM (Employees AS E INNER JOIN Orders AS O ON
E.EmployeeID = O.EmployeeID)
INNER JOIN [Order Details] AS OD ON O.OrderID =
OD.OrderID
WHERE OD.ProductID IN (4, 5)

The rules for union queries in Access SQL are as follows:

All queries in a UNION must request the same number of fields, but they
don't have to be the same size or data type (this restriction does exist in other
database systems).

Use aliases only in the first SELECT statement, because they are ignored in
all others

You can use a GROUP BY or HAVING clause in each query argument to


group the returned data

You can use an ORDER BY clause at the end of the last query argument to
display the returned data in a specified order. In the ORDER BY clause, refer
to fields by what they are called in the first SELECT statement.

Part III: Updating Data and DDL Queries

It goes without saying that caution should be exercised whenever


you run a query that can change or delete data in a table. It is a
good idea to backup your database or to work with test tables when
you are in a testing mode.
The UPDATE Query

Example 41:
Change the contact name for Customer ID "AROUT" to "John
Smith"

First, run this SELECT query to look at the


existing data:
SELECT CustomerID, ContactName
FROM Customers

(Note that the contact name for Customer ID


"AROUT" is '"Thomas Hardy".)

Next, run the UPDATE query:


UPDATE Customers
SET ContactName = 'John Smith'
WHERE CustomerID = 'AROUT'

Finally, run another SELECT query to verify the


change that you made:
SELECT CustomerID, ContactName
FROM Customers

(Note the change)


Note: Without the WHERE clause in the UPDATE,
ALL records would have the ContactName field
updated to 'John Smith' (and that wouldn't be
good).
Example 42:
Due to an increase in the price of sugar, you must increase the unit
price of all products in the "Confections" category
(Category ID 3) by 3%.

First, run a SELECT query to look at the existing


data:
SELECT * FROM Products ORDER BY
CategoryID

Next, run the UPDATE query:


UPDATE Products
SET UnitPrice = UnitPrice * 1.03
WHERE CategoryID = 3

Finally, run another SELECT query to verify the


changes that you made:
SELECT * FROM Products ORDER BY
CategoryID

Although not shown in the examples, you can change multiple fields
with the SET clause by separating each "column = value" item with
a comma:
UPDATE Customers SET ContactName = 'John
Smith', ContactTitle = 'Sales Manager', FAX =
'123-456-7890' WHERE ...

Combining UPDATE with INNER JOIN

A very useful feature of the UPDATE statement is its ability to join


tables so that you can update data in one table based on data in
another table. Such an update is sometimes called a "batch update"
or "mass update". (Not all database systems allow this form of the
UPDATE statement.)
For example, suppose price updates for certain products were
entered into an Excel spreadsheet and you needed to update the
UnitPrice field of the Products table with those new prices. You
could link to the Excel spreadsheet (which would cause Access to
look at the spreadsheet as if it were a table), then run the UPDATE
query using the Products table and the linked table. The example
below shows you how to do all that:

Open Excel, and create the simple spreadsheet shown below.


Save the spreadsheet as PriceUpdate.xls (it does not matter
what folder you save it to, but you will need to remember the
location for the steps that follow), then exit Excel.

Back in Access (in our NWINDVBP database), go to the File


menu and select Get External Data -> Link Tables, as shown
below:

In the Link dialog box that comes up, select "Microsoft


Excel(*.xls)" from the "Files of type" drop-down list, navigate to
the folder where you saved the spreadsheet, select the
PriceUpdate.xls file and click the Link button:

The Link Spreadsheet Wizard appears. The initial preselections should be correct, so click Next.

On the next page of the wizard, ensure that the "First row
contains column headings" box is checked (see below). After
checking the box (or verifying that it is checked), click Next.

On the last page of the wizard, type PriceUpdate for the linked
table name. When you are done, click Finish.

You should get a message that the wizard completed


successfully. You should then see an entry for the linked table in
the Tables tab of the Access database (it will appear in the list of
tables with a special icon):

At this point, PriceUpdate can be used just like any other table in
the database.
Example 43:
Update the unit price data in the Products table with data for the
corresponding products in the PriceUpdate spreadsheet.

First, run a SELECT query to look at the existing


data (for the sake of the example, we know that we
are going to update four particular products):
SELECT ProductID, ProductName,
UnitPrice
FROM Products
WHERE ProductID IN (4, 5, 14, 17)

Next, run the UPDATE query:


UPDATE Products INNER JOIN
PriceUpdate
ON Products.ProductID =
VAL(PriceUpdate.ProductID)
SET Products.UnitPrice =
PriceUpdate.UnitPrice
Note: The VAL function was used on the
PriceUpdate.ProductID field because when the
PriceUpdate spreadsheet was linked, Access
treated that field as text rather than numeric (and
the Link Wizard does not provide a way to specify
the data type of the linked fields). The ProductID
from the spreadsheet must be treated as a number
in order to join with the ProductID from the
Products table. Access did not have a problem
maintaining the numeric data type of the unit price,
which contains a decimal point.
When you run the above UPDATE query, you may
get a prompt similar to the following. For our
example, you should respond Yes.

Finally, re-run your SELECT query from above to


see the results of your changes:
SELECT ProductID, ProductName,
UnitPrice
FROM Products
WHERE ProductID IN (4, 5, 14, 17)

The DELETE Query

Example 44:
Mario Pontes from the Hanari Carnes company calls to tell you to
remove the Manjimup Dried Apples from the order that was placed
on August 8, 1994. You determine that this is order ID 10250 and
that the product in question is Product ID 51.

First, run this SELECT query to look at the


existing data:
SELECT * FROM [Order Details]
WHERE OrderID = 10250

Next, run the DELETE query:


DELETE FROM [Order Details]

WHERE OrderID = 10250


AND ProductID = 51
Note that you must specify BOTH OrderID AND the
ProductID so that you delete the one exact row
form the table. Otherwise, you will delete too much
data (and your other customers will not be happy!)
When you run the above DELETE query, you may
get a prompt from Access telling you that 1 row will
be deleted and that the action cannot be undone.
For our example, you should respond Yes.

Finally, re-run the SELECT query from above to


verify the results:
SELECT * FROM [Order Details]
WHERE OrderID = 10250

Warning: If you issue a DELETE statement without a WHERE


clause, you will delete ALL records in that table (the table itself and
its structure will remain intact). To completely remove a table, use
the DROP TABLE statement.
Although a hands-on example will not be given here, just as an
UPDATE query can update records in one table based on matching
data in another table, a DELETE query can also be based on a
multiple-table join (records in one table can be deleted based on
matching values in another table).
This (non-hands-on) example query joins the Categories table to
the Products table, and deletes records in the Products table that
match the selection criterion specified for the Categories table:
DELETE Products.*
FROM Categories INNER JOIN Products
ON Categories.CategoryID =
Products.CategoryID
WHERE Categories.CategoryName =
'Beverages'

The Append Query (INSERT INTO)

The INSERT INTO statement has two basic formats. To insert one
row into a table, you can use the INSERT INTO ... VALUES format;
to insert multiple rows into a table from another table, you can use
the INSERT INTO ... SELECT format. The INSERT INTO ...
VALUES format will be shown first.
Example 45:
Insert a record for our new shipper, International Parcel Service.
Their phone number is (800) 888-9999.
INSERT INTO Shippers (CompanyName,
Phone)
VALUES ('International Parcel
Service', '(800) 888-9999')
To check out the results, do a SELECT query:
SELECT * FROM Shippers

Note that in the INSERT statement above, the ShipperID was NOT
specified. This is because the ShipperID field is
defined as an Autonumber field, thus, whenever a
new record is added to the Shippers table, the
ShipperID field will automatically populate with the
next available number.
In the next example, we will use the SQL DDL statement CREATE
TABLE to create a new table. Then we will use INSERT INTO with
the SELECT option to populate this new table with some data from
the Customers table.
Creating a New Table

The Access SQL CREATE TABLE command has this basic syntax:
CREATE TABLE tablename (
field1 type [(size)] [NOT NULL] [singlefield CONSTRAINT clause]
[, field2 type [(size)] [NOT NULL] [singlefield CONSTRAINT clause]
[, ...]]
[, mutliple-field CONSTRAINT clause [,
...]])
The CREATE TABLE statement has these parts:
tablename

The name of the table to be created.

field1, field2

The name of field or fields to be created in the new table. You must create at least one field.

type

The data type of field in the new table. The keywords that can be used are shown
below:
Table field
data type in
Access UI
Yes/No
Number (Byte)
AutoNumber
(Long Integer)
Currency
Date/Time
Number
(Double)
Number (Long
Integer)
OLE Object
Memo
Number
(Single)

CREATE TABLE keyword(s)

BOOLEAN, BIT, LOGICAL, LOGICAL1, YESNO


BYTE, INTEGER1
COUNTER, AUTOINCREMENT
CURRENCY, MONEY
DATETIME, DATE, TIME, TIMESTAMP
DOUBLE, FLOAT, FLOAT8, IEEEDOUBLE,
NUMBER, NUMERIC
LONG, INT, INTEGER, INTEGER4
LONGBINARY, GENERAL, OLEOBJECT
LONGTEXT, LONGCHAR, MEMO, NOTE
SINGLE, FLOAT4, IEEESINGLE, REAL

Number
(Integer)
Text

SHORT, INTEGER2, SMALLINT


TEXT, ALPHANUMERIC, CHAR, CHARACTER,
STRING, VARCHAR

(Note: If CHAR or CHARACTER is used, a fixed-length text field is established; this is the only way
a fixed-length text field can be defined. In the Access UI, Text fields are always variable-length and
there is no way to specify otherwise there.)
size

The field size in characters (Text fields only). If size is omitted for a Text field, 255 is the default.

Specifies that the field may not contain NULL values (an entry is required)
single-field
This clause has the following syntax:
CONSTRAINT
CONSTRAINT constraint-name {PRIMARY KEY | UNIQUE | NOT
clause
NULL |
REFERENCES foreigntable [(foreignfield1, foreignfield2)]}
NOT NULL

If PRIMARY KEY or UNIQUE is specified, an index of that type is established for this field. NOT
NULL can either be specified as a named constraint or as a stand-alone clause (as seen above).
The REFERENCES option establishes this field as foreign key, related to the primary key in another
table.

multiple-field
This clause has the following syntax:
CONSTRAINT
CONSTRAINT name {PRIMARY KEY (primary1[, primary2 [,
clause
...]]) |
UNIQUE (unique1[, unique2 [, ...]]) |
NOT NULL (notnull1[, notnull2 [, ...]]) |
FOREIGN KEY (ref1[, ref2 [, ...]])
REFERENCES foreigntable [(foreignfield1 [, foreignfield2
[, ...]])]}

Example 46:
Create a new table called US_CUSTOMERS, which has the same
structure as the existing Customers table.
CREATE TABLE US_CUSTOMERS
(CustomerID TEXT(5) CONSTRAINT
PrimaryKey PRIMARY KEY,
CompanyName TEXT(40) NOT NULL,
ContactName TEXT(30),
ContactTitle TEXT(30),
Address TEXT(60),
City TEXT(15),
Region TEXT(15),
PostalCode TEXT(10),
Country TEXT(15),
Phone TEXT(24),
Fax TEXT(24))
If you switch over to the Tables tab, you'll see that
US_CUSTOMERS has been added to the list of
tables.

If you click the design button, you'll see how the fields have been
set up based upon what has been coded in the CREATE TABLE
statement. Note that the CustomerID field has been designated as
the primary key and that by specifying NOT NULL for
CompanyName, the Required property is set to "Yes".

Example 47:
Populate the US_CUSTOMERS table with data from the Customers
table. Include only those rows for which Country is "USA".
INSERT INTO US_CUSTOMERS (CustomerID,
CompanyName,
ContactName,
ContactTitle,
Address,
City,
Region,
PostalCode,
Country,
Phone,
Fax)
SELECT CustomerID,
CompanyName,
ContactName,
ContactTitle,
Address,
City,
Region,
PostalCode,
Country,
Phone,
Fax
FROM Customers
WHERE Country = 'USA'
Check your results with a SELECT statement:
SELECT * FROM US_CUSTOMERS

Note: Although it is a "best practice" to specify the column names on


both the INSERT part and the SELECT part of the
query above, in the case where ALL fields from the
source table will be inserted into the target table, you
could get away with a shortened form of this query, as
follows:
INSERT INTO US_CUSTOMERS
SELECT *
FROM Customers
WHERE Country = 'USA'

Changing the Table Structure


Adding a Column
Example 48:
Add a one-character field called CUSTOMER_TYPE to the
US_CUSTOMERS table.
ALTER TABLE Customers
ADD RG_CODE TEXT(1);
Verify your results by looking at the
US_CUSTOMERS table in design view:

To populate the new column in Access, you can an


UPDATE statement. In our example, we want to set
the RG_CODE to "W" for states on the west coast
(California, Oregon, or Washington). The query is:
UPDATE Customers SET RG_CODE = 'W'
WHERE Region IN ('CA', 'OR', 'WA')
Verify the results with a SELECT statement:

SELECT CustomerID, CompanyName, Region, RG_CODE

FROM US_CUSTOMERS

Changing a Column Definition


In Access, you cannot use the ALTER TABLE statement to change
the size or data type of a column. To do that you must create a new
table that duplicates the original table but has the new column
definition. You can then copy the data from the old table to the new
table (using the SQL INSERT statement), delete the original table,
and rename the new table to the old name. If the old table has
relationships with other tables, those relationships must be deleted
before you can delete the old table. Once the new table is in place,
the relationships with the other tables can be re-established.
Some database systems, such as Oracle, let you change a column
definition with the MODIFY clause of the ALTER TABLE statement.
The following is acceptable in Oracle (but not Access):
ALTER TABLE US_CUSTOMER
MODIFY Address VARCHAR2(75);
Note: In Oracle, a variable length text field is specified with the
keyword VARCHAR2.
Deleting a Column
Example 49:
Drop the Fax column from the US_CUSTOMERS table.
ALTER TABLE US_CUSTOMERS
DROP COLUMN Fax
Verify the results by looking at the US_CUSTOMERS table in design view.

DROP COLUMN is not supported by all database


systems (such as Oracle). To accomplish this in a
system that does not support DROP COLUMN, the
following four steps would be necessary:
1. create new table, leaving out the column to be
dropped
2. copy the other columns over from the new table
3. drop the old table
4. rename the new table to the old table name.
Dropping and Adding Constraints
The ALTER TABLE statement can also be used to drop a constraint
from or add a constraint to an existing field in a table. In the next two
exercises, we will drop the primary key constraint from the
US_CUSTOMERS table, then add it back.
Example 50:
Drop the primary key constraint from the US_CUSTOMERS table.
(Recall from the CREATE TABLE statement that we named that
constraint PrimaryKey.)
ALTER TABLE US_CUSTOMERS
DROP CONSTRAINT PrimaryKey
Verify your results by looking at the US_CUSTOMERS table in
Design View. Note that the Primary Key designation is
gone.
Example 51:
Add the primary key constraint back to the US_CUSTOMERS table.
ALTER TABLE US_CUSTOMERS
ADD CONSTRAINT PrimaryKey PRIMARY
KEY(CustomerID)
Verify your results by looking at the US_CUSTOMERS table in
Design View. Note that the Primary Key designation is
back.
Deleting a Table
Example 52:
Get rid of the US_CUSTOMERS table.
DROP TABLE US_CUSTOMERS
Verify your results by looking at the Tables tab of the database.
Note that US_CUSTOMERS is gone.
It goes without saying that you should be VERY
CAREFUL when dropping a table, or for that matter,
when deleting data. Make sure you have a backup.
Creating a Database Structure from Scratch

This last example shows you how you can generate an entire
database structure using CREATE TABLE statements. This
exercise has you build your own version of the BIBLIO.MDB
database that comes with both Access and VB. (If you do not have
BIBLIO.MDB, you can download it here.)

On your hard disk, locate BIBLIO.MDB and open it.


Examine the table structures in the tables' design view.
Go to Tools -> Relationships and examine the ways in which
the tables are related.
Close the database (but leave Access open)
Go to File -> New Database, and select a blank database

When asked to name the new database, call it


MYBIBLIO.MDB

In SQL view, enter the following four CREATE TABLE


queries:

CREATE TABLE Authors


(Au_ID AUTOINCREMENT CONSTRAINT Au_ID_PK PRIMARY KEY,
Author TEXT(50),
[Year Born] SHORT);

CREATE TABLE Publishers


(PubID AUTOINCREMENT CONSTRAINT PubID_PK PRIMARY KEY,
Name TEXT(50),
[Company Name] TEXT(255),
Address TEXT(50),
City TEXT(20),
State TEXT(10),
Zip TEXT(15),
Telephone TEXT(15),
Fax TEXT(15),
Comments MEMO);

CREATE TABLE Titles


(Title TEXT(255),
[Year Published] SHORT,
ISBN TEXT(20) CONSTRAINT ISBN_PK PRIMARY KEY,
PubID LONG CONSTRAINT PubID_FK REFERENCES Publishers(PubID),
Description TEXT(50),
Notes TEXT(50),
Subject TEXT(50),
Comments MEMO);

CREATE TABLE [Title Author]


(ISBN TEXT(20) CONSTRAINT ISBN_FK REFERENCES Titles(ISBN),
Au_ID LONG CONSTRAINT Au_ID_FK REFERENCES Authors(Au_ID),
CONSTRAINT TA_PK PRIMARY KEY(ISBN, Au_ID));

Examine your results in the tables' design view and in Tools ->
Relationships.

Post to Facebook
Post to Twitter
Add to LinkedIn
Post to Delicious
Post to Digg
Post on Google Buzz
Add to Google Bookmarks
Send via Gmail
Share on Google Reader
Add to Evernote
Print with PrintFriendly
Send via Yahoo Mail

Similar links
Getting Extended Info From WAV Files In Visual Basic
Start the Windows Screen Saver Using a Win32 API
Creating PDF files in Visual Basic
Simple Windows API Example
Calling Windows APIs
VB6 Animated Charts (With FusionCharts)
Convert C Strings to VB Strings
Activate Any Window With API
Move The Mouse in VB
Advanced Shell In Visual Basic

If you enjoyed this post, subscribe for updates (it's free)


Email Address...

Introduction to SQL

Subscribe

Fri, 01/11/2013 - 08:16 Andy Watson (not verified)

Very good, I have sat and worked through all of the examples, I was very impressed with
how comprehensive and easy to understand this was.
***However** *
I Think there is a mistake on Example 48, I know I new to SQL, but I am pretty sure that,
"Example 48:
Add a one-character field called CUSTOMER_TYPE to the US_CUSTOMERS table.
ALTER TABLE Customers
ADD RG_CODE TEXT(1);"
Should be
ALTER TABLE US_CUSTOMERS
ADD RG_CODE TEXT(1);
I really like you site and I am a genuine user, I am also very pleased with the results.
Thanks for all the help, continue the good work
Andy
reply

Tnat/s good manual, simple

Sun, 03/18/2012 - 03:12 Anonymous (not verified)

Tnat/s good manual, simple for understanding, even in fact that my knowledge of english
is quite poor.
reply

Probably the best tutorial

Fri, 03/16/2012 - 18:35 Eric from Sweden (not verified)

Probably the best tutorial I've seen around regarding this topic.
reply

database

Sun, 03/04/2012 - 08:02 Philip (not verified)

uhmm can u please give me some codes about


codes for finding the sum of database fields then the answer will display on label of form
in vb6.0 please
i need idea.. from all of u..
reply

wow thanks my friend!

Wed, 02/15/2012 - 10:13 Anonymous (not verified)

wow thanks my friend! appreciated


reply

LIKE statement

Sat, 10/01/2011 - 08:29 Aiman (not verified)

Hello,
This is very good tutorial. Thanks
I have created several tables in Access. I use VB6 to manipulate these tables using SQL
statements.
The LIKE statement is not working, here is the SQL statement, please tell me what is
wrong with it:
rsMyRS.Open "SELECT * FROM house WHERE price LIKE '*'", myDatabase
Thanks
Aiman
reply

recordset.open "Select *
From

Sat, 03/24/2012 - 19:55 drlukito mppm (not verified)

recordset.open "Select * From ID where ID like '" & "%" & Text1.Text & "%" & "'
",Database
I used this code if you want to select from textbox where firt and last text don't know
reply

This is my experiment

Thu, 11/10/2011 - 22:46 Anonymous (not verified)

dude, this is my experiment....


i dont know if it is correct or not....
i use the like statement like this,
example code
recordset.open "Select * From ID where ID like '" & text1.text & "' ",Database
------------------------------------------------------------------------------------------------try this and if it is error ask this site....
ehehe
reply

Done!

Sun, 10/09/2011 - 10:42 ChrisGT7

Don't use the '*' character.


Use the '%' instead. So:
rsMyRS.Open "SELECT * FROM house WHERE price LIKE '%'", myDatabase
ChrisGT7
reply

SQL connection

Mon, 08/15/2011 - 05:19 Digital (not verified)

I have designed a calculator that would be calculating students GPAs, and i want the
calculator to be saving using Access db with an SQL . Please i want someone to give me
a step by step process od doing it........ my E-mail Address: otorok@yahoo.com. thanks
reply

Error?

Mon, 06/13/2011 - 19:19 Bryce (not verified)

Hi, I think you have made a mistake. The line item total shouldn't be :
Format$(UnitPrice * Quantity * (1 + Discount)
Currently this doesn't discount the prices at all; it actually raises them! Instead, it should
be :
Format$(UnitPrice * Quantity * (1 - Discount)
I don't know if this was done on purpose (I don't know why it would be..), so I'm just
putting it out there.
reply

Thanks you for your detail


explanation

Thu, 04/28/2011 - 03:23 Aung Ko Ko (not verified)

Dear Sir
Thanks you so much for detail explanation for writing SQL statement in ACCESS.
It would be most appreciated if you also explain about detail explanation for writing micro
in ACCESS.
Thanks
reply

its very good tutorial..thanx

Fri, 04/15/2011 - 19:43 only one (not verified)

its very good tutorial..thanx a lot


reply

Thank you so much for your

Fri, 04/15/2011 - 17:24 Sivasweety (not verified)

Thank you so much for your SQL Tutorial.... Really useful..... Why the rain in comming
regularly...to help people of world.... because
you people...helping others.... so God satisfied and sending the rain... Thank you....
reply

Great ....

Mon, 03/14/2011 - 21:59 Renjith Krishnan (not verified)

Sir,
This is a great service .....
May god bless you and your family...
Thank you very much.
Ragards
reply

connectivity of vb 6 to
sql 2005

Sun, 02/20/2011 - 08:56 SANKET BERDE (not verified)

I need the tutorial for connectivity of vb 6.0 with SQL server 2005. And step by step

process of Adding, Updating the database or Deleting the database value or values on
the button click on the VB form. Please Help ..............
reply

awesome!!

Thu, 02/03/2011 - 00:12 maeya09 (not verified)

this is a great help for us..thanks a lot!!


reply

awesome!!

Thu, 02/03/2011 - 00:12 maeya09 (not verified)

this is a great help for us..thanks a lot!!


reply

an man??!

Thu, 02/03/2011 - 00:09 Anonymous (not verified)

k kadacul man sadi!!


reply

The Best!

Tue, 01/04/2011 - 20:22 Josua (not verified)

Hey, thanks it was a very good compilation.


It is very beneficial to us instructors. Thanks..
reply

Encrypting passwords

Thu, 12/23/2010 - 05:34 curtis

Hi co-members! can any of you help me with a way in which i can encrypt passwords
stored in database so that some one cant get the password even if he/she manages to
open the database that contains the passwords?
reply

dfgdfhyrtgnhjgfffffffffffffff

Thu, 12/23/2010 - 03:28 Anonymous (not verified)

dfgdfhyrtgnhjgfffffffffffffffffffnhj
gggggggggggggggggggggggggggghhhhhhhhhhhhhhhgfgfgfgfgfgfgfgfgfhgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfgfhhhhhhhhhhhhhhhhfggggggggggggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhdffffffffffffffffffffffffgfhfhgfhhhhhhhhhhhhhhhhhfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgffffffffffffffffffffffffffffffffffffffffffffffnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnndc
gftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgftgfthhhhhhhhhhhhhh
reply

stupid fellow

Sun, 04/01/2012 - 01:08 Anonymous (not verified)

stupid fellow
reply

SQL Query

Thu, 12/23/2010 - 00:37 RohitSonar (not verified)

How to us SQL query in VB6,


In
DataEnvironment > Connection > Command > Properties > SQL Statements.
Please tell me how to fetch text box or combobox values in the SQL statements.
I have used this query but it is not working properly
select * from TABLENAME where FIELD = '"& Textbox.text &"'
Thanks in advance,
Rohit
My E-mail ID is - rohitsonar@hotmail.com
reply

Joining text box for


search in sql

Wed, 12/29/2010 - 09:25 Mrutunjaya (not verified)

Try this
Dim Find As String
Find="Select * from TABLENAME where TABLENAME.FIELD = " & "'" & Text1.Text &
"'"
Data1.RecordSource = Find
Data1.Refresh
reply

Thanks!

Wed, 12/08/2010 - 02:02 blueeyes7 (not verified)

Just what I need! Tnx so much :-)


reply

Just what I needed

Thu, 10/28/2010 - 05:19 Phil B (not verified)

Very Good! Somehow, you've kept it very simple but very informative.
reply

tnx

Sun, 09/12/2010 - 06:33 Anonymous (not verified)

very helpful =)
reply

about sql and vb

Sun, 08/22/2010 - 02:58 dashang makwana (not verified)

how can i add sql DB in VB?


reply

VERY HELPFUL..

Fri, 08/06/2010 - 18:55 Chams (not verified)

I can actually learn it myself. But also, I still need to ask my prof for further explanation.
Though it really REALLY HELPED ME A LOT! You're now my idol man! I'll read the rest.
:) God bless and keep sharing what you know.
reply

Greatest Coading

Thu, 07/08/2010 - 08:02 Khan Aamer (not verified)

It is nice tetorial for SQL in VB its gives a strong Back end for Storages Data thank you
reply

Introduction to SQL
(Structured Query Language)

Tue, 04/20/2010 - 02:11 Bernard (not verified)

Thank you, this is one of the best information I have seen about SQL.
I found explanations which are nor mentionned in a book I considered as a good one
(The Practical SQL HandbooK - Bowman, Emerson and Darnovsky)
I have been playing around with VBA since excel 95 but because of problems with Excel
2007, I decided one month agoto step over and use VB6.0 and Access (Only the
database, not the other functions...)
I am writing a school management application...
Actually, I'd like to use MySQL but I don't know where to start...
Thanks a lot again
Cheers
Bernard
reply

Report

Wed, 04/14/2010 - 01:24 wassim (not verified)

This tutorial is very useful to me....its allobrate the information correctly............i have
request to provide the sql2000 and vb6 sw ..and coding and explanation for same
project
reply

It was nice but one still


something missing

Sun, 01/03/2010 - 23:59 Anonymous (not verified)

Hello Everyone out there, the above tutorial is fabulous but I found something still
missing. I was looking for example:
If the NEW ORDER has been placed and if there 1000 items which are of same catagory
and If the customer orders only for 200 items then to my amazement not find in this vast
SQL information that how the one SELECT or DELETE from the STOCK only 200 items
out of 1000 items to place the order. I know it not very complicated but I really dont have
idea about it as Im newbie to SQL but was expecting the query on this website but I
found hopeless myself. Anyhow if the authors of this website are reading these
comments regularly then please also add the said idea as well. Thank you all.
reply

SELECT TOP 200 FROM

Tue, 04/27/2010 - 18:22 Anonymous (not verified)

SELECT TOP 200 FROM WHERE


or
DELETE TOP 200 FROM WHERE
reply

nice, your pdf link goes to

Sat, 11/28/2009 - 12:55 Anonymous (not verified)

nice, your pdf link goes to a lets say, not so nice to my pc site.
reply

great!really helpful

Tue, 11/24/2009 - 20:12 ludelyn (not verified)

i like this tutorial....very informtive...


think with this help
i will be able to pass my vb subject!!!
thanks a lot!!!
reply

Thanks

Wed, 09/09/2009 - 00:18 ParesH (not verified)

Thank you for such an informative and handy tutorial.

reply

This is called "Exact" &

Sun, 08/30/2009 - 16:03 zchan (not verified)

This is called "Exact" & purely "Compact" teaching. Hmm!


reply

Brilliant!

Tue, 05/12/2009 - 08:25 Franjdea (not verified)

Thanks guys, this is really helpful!


reply

hi

Fri, 04/17/2009 - 03:23 shivasharan (not verified)

This is a AWESOME tutorial.


really great.
reply

Thanks

Thu, 02/12/2009 - 09:43 barmycoder (not verified)

Excellent! Thanks a lot............


reply

Excelent

Tue, 01/27/2009 - 21:18 Philip (not verified)

Great jog and helps the SQL beginners a lot.


reply

Tutorial Lacks Something

Mon, 01/19/2009 - 13:04 Anonymous (not verified)

This tutorial is lacking.. why is it all TEXT? Please update this with NUMBER or DATE
fields..
reply

superb man best topic i


have

Mon, 12/15/2008 - 09:16 Anonymous (not verified)

superb man best topic i have ever seeen coooooooooooooooooooooooooooooool


reply

HTML - change your H6


elements

Tue, 11/25/2008 - 14:48 Anonymous (not verified)

Nice content, but you need HTML formatting help. An "H6" element is for a 6th-level
heading, and it uses a small font by default.
reply

LIKE function

Mon, 09/29/2008 - 21:38 John_01 (not verified)

question: How do use LIKE function in SQL statement if the string you are trying to locate
contains the character: '
example: SELECT * FROM Table WHERE Field LIKE '%O'Neil%'
it is giving me a syntax error, missing operator.
how do i solve this.
Thanks!
reply

great!

Mon, 08/25/2008 - 08:28 babes (not verified)

the page was very helpful and easy to understand. thank you - good job!
reply

good

Tue, 08/12/2008 - 05:30 Dipalee (not verified)

good
reply

Thu, 12/23/2010 - 03:27 Anonymous (not verified)

gfgfgfgfgfgfgfgfgfgfgfgfgfgfg
gfgfgfgfgfgfgfgfgfgfgfgfgfgfgf
reply

What a marvelous helper

Fri, 07/18/2008 - 21:35 Okusitino (not verified)

I am so happy for the creator or develoers of this site whom i find it very interested and
very helpful...I do hope that God will give you strength to continue on this work...You light
your world to the people and God will even give you more light...and you will get smarter
as days go....
Just From A Tongan Crusader For Christ
reply

Excellent. It is a pity that

Tue, 03/04/2008 - 22:25 Anonymous

Excellent.
It is a pity that this was not around when I was learning SQL
Rob
reply

Post new comment


Your name:
Anonymous
E-mail:
The content of this field is kept private and will not be shown publicly.

Homepage:

Subject:

Comment: *

Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
Lines and paragraphs break automatically.
You can enable syntax highlighting of source code with the following tags: <code>,
<blockcode>. The supported tag styles are: <foo>, [foo].

More information about formatting options


Word verification: *
(verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new
image will be generated. Not case sensitive.

Preview

Unless otherwise noted, all content on this site and in the source samples is Copyrighted
2011 by the owner of vb6.us. All rights reserved - Contact Information

S-ar putea să vă placă și