Chapter 15. Programming DAO: Data Definition Language

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, DatabaseVardenotes 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.

Creating a Database

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.

Notes

  • 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.

Example 15-1. A CreateDatabase method example
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.Close

End 
                     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.

Opening a Database

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.

Creating a Table and Its Fields

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.

Notes

  • 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.

Table 15-1. Constants for the Type property

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

Note

To remove a field from a TableDef object, use the Delete method.

Field objects have a variety of properties, among which are:

AllowZeroLength

True if a zero-length value is valid for a text or memo field. (Setting this property for a nontext field generates an error.)

DefaultValue

Sets or returns the default value of a Field object.

Required

True indicates that a null value is not allowed.

ValidationRule and ValidationText

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.

Example 15-2. A CreateTableDef method example
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 tblNew

End 
                        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.

Design view of table generated from running exaCreateTable
Figure 15-1. Design view of table generated from running exaCreateTable

Incidentally, TableDef objects also have ValidationRule and ValidationText properties, used to set validation rules that involve multiple fields in the table.

Changing the Properties of an Existing Table or Field

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.

Creating an Index

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.

Example 15-3. A CreateIndex method example
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 idx

End 
                  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.

Indexes view of BOOKS table from running exaCreateIndex
Figure 15-2. Indexes view of BOOKS table from running exaCreateIndex

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:

DistinctCount

Gives the number of distinct values in the index.

IgnoreNulls

Determines whether a record with a null value in the index field (or fields) should be included in the index.

Primary

Indicates that the index fields constitute the primary key for the table.

Required

Determines whether all of the fields in a multifield index must be filled in.

Unique

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.

Creating a Relation

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.

Table 15-2. Attributes for a Relation object

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

Notes

  • 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.

Table 15-3. The SALESREGIONS 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).

Example 15-4. A CreateRelation method example
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 rel

End 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.

Relationships window after running exaRelations
Figure 15-3. Relationships window after running exaRelations

Creating a QueryDef

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.

Notes

  • 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.

Running a Query

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.

Example 15-5. A CreateQueryDef method example
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%.

Example 15-6. A new action query example
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.Execute

End 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"

Properties of a QueryDef Object

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.

Table 15-4. Possible query-type constants

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.

Example 15-7. A RecordsAffected property example
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 If

End Sub

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.231.128