In the overview of DAO, I noted that Data Access Objects consists of two conceptually distinct components: a data definition language (DDL), which allows us to create or access some basic database system objects, like databases, table definitions, and indexes; and a data manipulation language (DML), which allows us to perform the practical operations of adding data (records) to our tables, deleting unwanted data, and modifying existing data. In this chapter, I discuss the DDL aspects of DAO.
Let us begin by noting the following:
To indicate variables of a certain type, I will write the type
name followed by the suffix Var
. For
example, DatabaseVar
denotes a variable of
type Database
, and
TableDefVar
denotes a variable of type
TableDef
.
In describing the syntax of certain methods, I will use square brackets ([ ]) to indicate optional items.
I will generally give the full syntax of methods, but will only give details on the more common options. Of course, full details are available through the Access help system.
Databases are created using the CreateDatabase
method of a Workspace object. The
general syntax of this method is:
SetDatabaseVar
= [WorkspaceVar
.]CreateDatabase _ (DatabaseName
,locale
[,options
])
where:
DatabaseName
is a string
expression representing the full path and name of the database
file for the database being created. If you don’t supply a
filename extension, then the extension .mdb
is automatically appended.
locale
is a string expression
used to specify collating order for creating the database. You
must supply this argument, or an error will occur. For the English
language, use the built-in constant dbLangGeneral
.
options
relates to specifying
encryption or use of a specific version of the Jet database
engine. For more information, please see Access help.
The CreateDatabase
method creates a new Database object,
appends the database to the Databases
collection, saves the database on disk, and then returns an
opened Database object, but the database
has no structure or content at this point.
To duplicate a database, you can use the CompactDatabase
method of a
Workspace object, specifying a different
name for the compacted database.
A database cannot be deleted programmatically
through DAO. To delete a database programatically, use the
KILL
statement in VBA.
Example 15-1 creates a new database named MoreBks.mdb on the directory c:/temp and then lists the tables that are contained in the database.
Sub
exaCreateDb( ) Dim dbNew As DATABASE Dim tbl As TableDef Set dbNew = CreateDatabase _ ("c: empMoreBks", dbLangGeneral) For Each tbl In dbNew.TableDefs Debug.Print tbl.Name Next dbNew.CloseEnd
Sub
The program in Example 15-1 displays the following list of tables:
MSysACEs |
MSysObjects |
MSysQueries |
MSysRelationships |
These tables are created by Microsoft Access for its own use.
To open an existing database, use the OpenDatabase
method of a Workspace object. The
syntax is:
SetDatabaseVar
= [WorkspaceVar
.]OpenDatabase _ (DatabaseName
[,exclusive
[,read
-only
[,source
]]])
where DatabaseName
is the name of an
existing database. (As indicated by the square brackets, the other
parameters are optional.) For information about the optional
parameters, see the Access help system.
It is important to remember to close a database opened through
the OpenDatabase
method. This
removes the database from the Databases
collection.
Tables are created using the CreateTableDef
method of a Database object. The
full syntax of this method is:
SetTableDefVar
=DatabaseVar
.CreateTableDef _ ([TableDefName
[,attributes
[,source
[,connect
]]]])
where:
TableDefName
is a string or
string variable holding the name of the new
TableDef object.
For information about the optional parameters, see the Access help system.
The new TableDef object must be
appended to the TableDefs collection using
the Append
method. However,
before appending, the table must have at least one field.
CreateTableDef
does not
check for an already used
TableDefName
. If
TableDefName
does refer to an object
already in the TableDefs collection, an
error will occur when you use the Append
method, but not before.
To remove a TableDef object from a
TableDefs collection, use the Delete
method.
Fields are created for a table using the CreateField
method of the TableDef object.
The syntax is:
SetFieldVar
=TableDefVar
.CreateField _ ([FieldName
[,type
[,size
]]])
where:
FieldName
is a string or string
variable that names the new Field
object.
type
is an integer constant that determines the data type of the new
Field object. (See Table 15-1.)
size
is an integer between 1
and 255 that indicates the maximum size, in bytes, for a text
field. This argument is ignored for other types of
fields.
Data type | Constant | Numerical value |
Boolean | dbBoolean | 1 |
Byte | dbByte | 2 |
Integer | dbInteger | 3 |
Long | dbLong | 4 |
Currency | dbCurrency | 5 |
Single | dbSingle | 6 |
Double | dbDouble | 7 |
Date/Time | dbDate | 8 |
Text | dbText | 10 |
Long Binary (OLE Object) | dbLongBinary | 11 |
Memo | dbMemo | 12 |
GUID | dbGUID | 15 |
To remove a field from a TableDef
object, use the Delete
method.
Field objects have a variety of properties, among which are:
True
if a
zero-length value is valid for a text or memo field.
(Setting this property for a nontext field generates an
error.)
Sets or returns the default value of a Field object.
True
indicates that
a null value is not allowed.
Used for validation of field values. (See the following example.)
The procedure in Example 15-2 creates a new table named NewTable, creates a new field named NewField, sets certain properties of the field and appends it to the Fields collection, and then appends the new table to the TableDefs collection.
Sub
exaCreateTable( ) Dim db As DATABASE Dim tblNew As TableDef Dim fld As Field Set db = CurrentDb Set tblNew = db.CreateTableDef("NewTable") Set fld = tblNew.CreateField("NewField", dbText, 100) ' Set properties of field BEFORE appending ' zero length value is OK fld.AllowZeroLength = True ' default value is 'Unknown' fld.DefaultValue = "Unknown" ' Null value not allowed fld.Required = True ' Validation fld.ValidationRule = "Like 'A*' or Like 'Unknown'" fld.ValidationText = "Known value must begin with A" ' Append field to Fields collection tblNew.Fields.Append fld ' Append table to TableDef collection db.TableDefs.Append tblNewEnd
Sub
Setting the validation properties of a field requires setting two properties. The ValidationRule property is a text string that describes the rule for validation, and the ValidationText is a string that is displayed to the user when validation fails. After running the code from Example 15-2, a new table appears in the Access Database window. (You may need to move away from the Tables tab and then return to that tab to see the new table.) Opening this table in Design View shows the window in Figure 15-1. Note that the Field Properties setting reflects the properties set in our code.
Incidentally, TableDef objects also have ValidationRule and ValidationText properties, used to set validation rules that involve multiple fields in the table.
I have remarked that some properties that are read/write before the object is appended to its collection become read-only after appending. One such example is the Type property of a field. On the other hand, the Name property of a field can be changed. This is an example of a change that can be made using DAO but not by using SQL.
Indexes are created using the CreateIndex
method for a TableDef object. Here
is the syntax:
Set IndexVar = TableDefVar.CreateIndex([IndexName])
Creating an index by itself does nothing. We must append one or more fields to the Fields collection of the index in order to actually index the table. Moreover, the order in which the fields are appended (when there is more than one field) has an effect on the index order. This is demonstrated in Example 15-3, in which a new index called PriceTitle is added to the BOOKS table.
Sub
exaCreateIndex( ) Dim db As DATABASE Dim tdf As TableDef Dim idx As INDEX Dim fld As Field Set db = CurrentDb Set tdf = db.TableDefs!BOOKS ' Create index by the name of PriceTitle Set idx = tdf.CreateIndex("PriceTitle") ' Append the price and then the Title fields ' to the Fields collection of the index Set fld = idx.CreateField("Price") idx.Fields.Append fld Set fld = idx.CreateField("Title") idx.Fields.Append fld ' Append the index to the indexes collection ' for BOOKS tdf.Indexes.Append idxEnd
Sub
Figure 15-2 shows the result of running the program from Example 15-3. (To view this dialog box, open the BOOKS table in design view, and select the Indexes option from the View menu.) The figure shows clearly why we first create two fields—Price and Title—and append them, in that order, to the Fields collection of the index.
As we discussed in an earlier chapter, an index for a table is actually a file that contains the values of the fields that make up the index, along with a pointer to the corresponding records in the table. Microsoft tends to blur the distinction between an index (as a file) and the fields that contribute to the index. Thus, to say that an index is primary is to say that the fields (actually, the attributes) that make up the index constitute a primary key.
With this in mind, some of the important index properties are:
Gives the number of distinct values in the index.
Determines whether a record with a null value in the index field (or fields) should be included in the index.
Indicates that the index fields constitute the primary key for the table.
Determines whether all of the fields in a multifield index must be filled in.
Determines whether the values in a index must be unique, thus making the index fields a key for the table.
Note that the difference between a primary key index and a unique values index is that a primary key is not allowed to have NULL values.
Relations are created in DAO using the CreateRelation
method. The syntax is:
SetRelationVar
=DatabaseVar
.CreateRelation _ ([RelName
[,KeyTable
[,ForeignTable
[,Attributes
]]]])
where:
RelName
is the name of the new
relation.
KeyTable
is the name of the
referenced table in the relation (containing
the key).
ForeignTable
is the name of the
referencing table in the relation (containing
the foreign key).
Attributes
is a constant, whose values are shown in Table 15-2.
Constant | Description |
dbRelationUnique | Relationship is one-to-one |
dbRelationDontEnforce | No referential integrity |
dbRelationInherited | Relationship exists in a noncurrent database that contains the two attached tables |
dbRelationUpdateCascade | Cascading updates enabled |
dbRelationDeleteCascade | Cascading deletions enabled |
All of the properties of a Relation object become read-only after the object is appended to a Relations collection.
Field objects for the referenced and referencing tables must be appended to the Fields collection prior to appending the Relation object to the Relations collection.
Duplicate or invalid names will cause an error when the
Append
method is
invoked.
To remove a Relation object from a
collection, use the Delete
method for that collection.
Example 15-4 illustrates the use of Relation objects. In this example, we will create a new relation in the LIBRARY database. The first step is to create a new table, using Microsoft Access. Call the table SALESREGIONS, and add two text fields: PubID and SalesRegions. Then add a few rows shown in Table 15-3 to the table.
PubID | SalesRegions |
1 | United States |
1 | Europe |
1 | Asia |
2 | United States |
2 | Latin America |
The code in Example 15-4 creates a relation between the PubID field of the PUBLISHERS table (the primary key) and the PubID field of the SALESREGIONS table (the foreign key).
Sub
exaRelations( ) Dim db As DATABASE Dim rel As Relation Dim fld As Field Set db = CurrentDb ' Create relation Set rel = db.CreateRelation("PublisherRegions", _ "PUBLISHERS", "SALESREGIONS") ' Set referential integrity with cascading updates rel.Attributes = dbRelationUpdateCascade ' Specify the key field in referenced table Set fld = rel.CreateField("PubID") ' Specify foreign key field in referencing table. fld.ForeignName = "PubID" 'Append Field object to Fields collection of ' Relation object. rel.Fields.Append fld ' Append Relation object to Relations collection. db.Relations.Append relEnd Sub
After running this code, make sure the Database window is active, and select Tools → Relationships from the Access menu bar. Then select Relationships → Show All, and you should see a window similar to that in Figure 15-3, showing the new relationship.
Creating a QueryDef object is done using the CreateQueryDef
method. The syntax is:
SetQueryDefVar
=DatabaseVar
.CreateQueryDef _ ([QueryDefName
][,SQLText
])
where QueryDefName
is the name of the
new QueryDef object and
SQLText
is a string expression that
constitutes a valid Access SQL statement.
If you include QueryDefName
,
the QueryDef is automatically saved
(appended to the appropriate QueryDefs
collection) when it is created. The Name property and the SQL
property of a QueryDef can be changed at
any time.
You can create a temporary QueryDef,
which is not appended to a collection, by setting the
QueryDefName
property to a
zero-length string (“”). You cannot change the name of a
temporary QueryDef.
If you omit the SQLText
argument, you can define the QueryDef by
setting its SQL property before or after you append it to a
collection.
To remove a QueryDef object from a
QueryDefs collection, use the Delete
method.
Recall from Chapter 6 that Microsoft Access supports several types of queries. In particular, a select query returns a recordset. An action query does not return a recordset, but rather takes action on existing data, such as making a new table, deleting rows from a table, appending rows to a table, or updating the values in a table.
If a QueryDef object represents an action
query, then we can use its Execute
statement to run the query. If the
QueryDef object represents a select query, then
we can open the corresponding result table (recordset) using the
OpenRecordset
method on the
QueryDef object. Let us illustrate. The code in
Example 15-5 creates
a new select query and displays the record count for the resulting
recordset.
Sub
exaCreateSelect( ) Dim db As DATABASE Dim qdf As QueryDef Dim strSQL As String Dim rs As Recordset Set db = CurrentDb ' Create an SQL SELECT statement strSQL = "SELECT * FROM BOOKS WHERE Price > 20" ' Create a new QueryDef object Set qdf = db.CreateQueryDef("NewQuery", strSQL) ' Open a recordset for this query Set rs = qdf.OpenRecordset ' Move to end of recordset rs.MoveLast ' Show record count MsgBox "There are " & rs.RecordCount & " books with price exceeding $20"End Sub
The code in Example 15-6 creates a new action query and executes it. The effect is to raise the price of each book in the BOOKS table by 10%.
Sub
exaCreateAction( ) ' Creates an action query and executes it Dim db As DATABASE Dim qdf As QueryDef Dim strSQL As String Set db = CurrentDb ' Create an SQL UPDATE statement ' to raise prices by 10% strSQL = "UPDATE BOOKS SET Price = Price*1.1" ' Create a new QueryDef object Set qdf = db.CreateQueryDef("PriceInc", strSQL) qdf.ExecuteEnd Sub
Note that once a QueryDef object exists,
we may still use the OpenRecordset
or Execute
methods to run the query. The
Execute
method can also be used
on a Database object to run an SQL statement.
Here is an example that reduces the price of each book in the BOOKS
table by 10%:
Dim db As DATABASE Set db = CurrentDb db.Execute "UPDATE BOOKS SET Price = Price*0.9"
When a QueryDef object is created or changed, Jet sets certain properties, such as DateCreated, LastUpdated, and Type. (Note that the QueryDefs collection may need refreshing before these properties can be read.) Some of the possible query types are listed in Table 15-4.
Constant | Query type | Value |
dbQSelect | Select | 0 |
dbQAction | Action | 240 |
dbQCrosstab | Crosstab | 16 |
dbQDelete | Delete | 32 |
dbQUpdate | Update | 48 |
dbQAppend | Append | 64 |
dbQMakeTable | Make-table | 80 |
The RecordsAffected property returns the number of records affected by the last application of the Execute method. Let us illustrate.
Example 15-7 modifies the earlier action-query example to perform the action (10% price increase) if and only if the increase will affect more than 15 books in the table. This is done using the BeginTrans, Committrans, and Rollback properties of the current Workspace object.
Sub
exaCreateAction2( ) Dim ws As Workspace Dim db As DATABASE Dim qdf As QueryDef Dim strSQL As String Set ws = DBEngine(0) Set db = CurrentDb ' Create an SQL UPDATE statement ' to raise prices by 10% strSQL = "UPDATE BOOKS SET Price = Price*1.1 ' Create a new QueryDef object Set qdf = db.CreateQueryDef("PriceInc", strSQL) ' Begin a transaction ws.BeginTrans ' Execute the query qdf.Execute ' Check the number of records affected and either roll back transaction or proceed If qdf.RecordsAffected <= 15 Then MsgBox qdf.RecordsAffected & " records affected " & _ "by this query. Transaction cancelled." ws.Rollback Else MsgBox qdf.RecordsAffected & " records affected " & _ "by this query. Transaction completed." ws.CommitTrans End IfEnd Sub
3.149.231.128