Đôi khi, có lẽ hầu như bạn sẽ tạo các bảng bằng tay. Tuy nhiên, thỉnh thoảng bạn có thể tìm thấy sự tiện ích của việc tạo bảng động, chẳng hạn như khi bạn cần duy trì kết quả trung gian để sử dụng lại cho các thao tác sau này. Access 2000 cho phép bạn làm điều này bằng cách sử dụng kỹ thuật ADO, kỹ thuật này cũng như kỹ thuật truyền thống Data Access Objects (DAO). Phần này sẽ bàn về cách tạo và quần lý bảng bằng cách sử dụng kỹ thuật ADO như thế nào. Khi bạn nghiên cứu phương pháp này, bạn sẽ có cơ hội tiếp thu những cải tiến trong thời gian tới về kỹ thuật truy xuất dữ liệu của Microsoft.
Sau khi tạo một bảng bằng chương trình, bạn thường muốn điển các dữ liệu vào bảng. Cho dù bạn không tạo bảng bằng chương trình, việc điển dữ liệu bằng chương trình vào nó cũng được quan tâm. Bạn có thể sử dụng các nguồn đữ liệu khác nhau để điển vào bảng dữ liệu Access. Phần này sẽ khảo sát việc sử dụng bảng của Access khác, một bảng tính Excel (như là một ví dụ của nguồn dữ liệu ISAM) và một nguồn dữ liệu ODBC, Bạn cũng sẽ nghiên cứu cách điển dữ liệu vào bảng của Access bằng cách sử dụng các nhà cung cấp cơ sở dữ liệu OLE (OLE DB) như thế nào và đối tượng DoCmởd Access gốc, đó là đối tượng tạo dễ dàng để liên kết với các nguồn dữ liệu từ xa. Không giống như việc sử dụng OLE DB, việc sử dụng DoCmd tạo nguồn dữ liệu liên kết khả dụng từ cửa sổ Database.
Tạo Bảng
Để thêm các bảng động, tất cả những điều bạn cần là sử dụng kỹ thuật ADO trong thư viện ADOX. Cũng như khi tạo một bảng trong cơ sở dữ liệu bằng tay, khi bạn tạo một bảng động bạn phải
Chương 3: THIET KE BANG
đặt tên cho nó, thêm các cột (column) vao bang va néi né vào trong tap hgp Tables.
Thủ tục MakeLocdlTable dưới đây tạo một bảng động. Nó bắt đầu bằng việc khai báo một đối tượng Catalog vA Table. Déi tượng Catalog 1a mét thing chifa trong giản dé dit ligu, bao gim tap hop Table. Tiép theo, thủ tục thuyết minh cho các đối tugng Catalog va Table. N6 dat tén bảng là FamiiyMembers2 và ấn định bốn cột bằng cách sử dụng 4 lần phương pháp Append lồng vào trong câu lệnh Wh...End. Mỗi phương pháp Append bao gồm một hằng xác định và một đối số chiờu dài nếu thớch hợp. Ba fủeld kiểu Text (chúng được tạo bằng cách chỉ ra kiểu đữ liệu œởđVarWChar) mỗi
fủeld đờu cú kớch thước rừ ràng. Thủ tục kết thỳc bằng việc nối thêm bảng đã hoàn tất vào tập hợp Tables cia Catalog va đóng đối tuong Catalog lai.
Sub MakeLocalTable()
Dim cati As ADOX.Catalog Dim tbl1 As ADOX.Table
"Tham chiếu các đối tượng cho bằng Set cat1 = New Catalog
cat1.ActiveConnection = CurrentProject.Connection Set tbl1 = New Table
'Đặt tên cho bằng và các cột nối thêm vào.
With tbl1
.Name = “FamilyMembers2"
.Columns.Append "FamID", adInteger .Columns.Append "Fname", adVarWChar, 20 .Columns.Append "Lname", adVarWChar, 25 .Columns.Append "Relation", adVarWChar. 30 End With
221
Nỗi thêm bằng mới vào tập hop Tables Và giải phóng tài nguyên catalog.
cat1.Tables.Append †bl1 Set catt = Nothing End Sub
Bảng dưới đây liệt kê các kiểu dữ liệu và các kiểu phụ được miêu tả bởi các hằng lớp DataTypeEnum ctia thu vin ADOX.
CAC HANG KiEU COLUMN VA SỰ TƯƠNG ĐƯƠNG KIỂU DỮ LIỆU
MANUAL
Hằng số Giá trị Kiểu dữ liệu Manual
AdBoolean 11 Yes/No
AdCurrency 6 Currency _
AdDate no Date/Time _
adDecimal 14 Number--Decimal -
-_--.. S______Number—Double
adGuid 72 Number—Replication ID
adinteger ao AutoNumber —
adInteger 3 Number—Long Integer
adLongVarBinary 205 OLE Object adLongVarWChar 203 Hyperlink
adLongVarWChar 203 Memo
_AdSingle 4 Number—Single
AdSmallint 2 Number—Integer
AdUnSignedTinyInt 17 Number—Byte
® Chương 3: THIẾT KẾ BẰNG
AdWChar 130 Text
Bảng trên có hai điểm đáng quan tam. Dau tién, kiéu dit liéu Hyperlink tương đương với kiểu đữ liệu Memo từ lập trình triển vọng. Thứ hai, không có kiểu dữ liệu riêng biệt cho các field kiểu AutoNumber trong thư viện ADOX. Nếu trong chương trình kiểm tra giỏ trị của thuộc tớnh 7ype của fủeld cú kiểu là AutoNumber, bạn sẽ nhận được giá trị là adlnfeger. Giá trị này không phản ánh trạng thái tự nhiên năng động của kiểu đữ liệu AuteNumber. Tuy nhiên Jet 4, có một kiểu dữ liệu riêng biệt, Indentify, nó tương
đương với kiểu dữ liệu AutoNumber. (Xem Chương 2 để biết thêm cách sử dụng kiểu đữ liệu này.). Trong phần trước “Tạo bảng dữ liệu bằng tay” cũng đã để cập đến nhiều từ khóa trong việc quản lý các field kiểu AutoNumber bằng chương trình.
Tránh Việc Thay Thế Bảng
Khi bạn thêm một bảng vào cơ sở dữ liệu bằng tay, nó rất dễ dàng kiểm tra xem tên bảng đó đã tổn tại hay chưa. Nếu bạn tình cờ thử lưu một bảng mà tên của nó trùng với tên bảng đã có trong cơ sở dữ liệu, Access sẽ báo cho bạn và hỏi bạn có muốn ghi đè lên bảng đã có sẵn hay không. Tuy nhiên khi bạn tạo một bảng đữ liệu bằng chương trình, Access VBA tạm dừng chương trình do một lỗi run-time khi thủ tục cố gắng tạo một bảng dữ liệu mới mà tên của nó đã tổn tại trong cơ sở dữ liệu. Vì thế bạn cần bẫy lỗi để giải quyết tình huống này. Có ít nhất hai giải pháp để làm điều này.
Một phương pháp tạo cảm ứng (sense) hay sử dụng nhất nhưng còn tùy thuộc vào bạn có thường xuyên tạo các bảng mới hay không.
Thủ tục M@keLocalTableErrCaitcher dưới đây sử dụng giải pháp bãy lỗi cổ điển. Đầu tiên, nó cho phép một thường trình thủ tục xử lý lỗi khách hàng do đó chương trình có thể xử lý các lỗi.
Câu lénh On Error ở đầu thủ tục thực hiện điểu này. Kế tiếp, nó
223
thử tạo và nối thêm cùng bang FamilyMembers2 như trong thủ tục MakeLocalTable. Néu bang đã tên tai trong Catalog, Access VBA sinh ra một lỗi (-2147217857) và chuyển diéu khién thường trình thủ tục xử lý 16i TableErrCatcher. Việc bẫy lỗi logic kiểm tra xem có lỗi "already exists" không. Nếu nó tìm ra lỗi này, nó sẽ xóa bảng đã có và trả quyền điều khiển về dòng gây ra lỗi. Điều này cho phép chương trình lưu lại bảng mới và thoát khỏi thủ tục một cách bình thường. Nếu có một lỗi khác xảy ra, thường trình thủ tục sẽ in số hiệu lỗi và câu diễn giải ra cửa sổ Immediate trước khi thoát khối thủ tục. Thủ tục không bao giờ kết thúc một cách khác thường với một thông báo hệ thống.
Sub MakeLocalTableErrCatcher() On Error GoTo TableErrCatcher Dim cat? As ADOX.Catalog Dim tbl1 As ADOX.Table
'Các đối tượng tham chiếu cho bằng Set cati = New Catalog
cat1.ActiveConnection = CurrentProject.Connection Set tbl1 = New Table
‘Dat tên cho bằng và các cột nối thêm.
With tbl1
.Name = "FamilyMembers2"
-Columns.Append "FamID", adInteger .Columns.Append "Fname", adVarWChar, 20 -Columns.Append "Lname", adVarWChar, 25 .Columns.Append “Relation", adVarWChar, 30 End With
Nối thêm bằng mới vào tập hợp Tables và giải phóng nguồn tài nguyên Catalog.
cat†1.Tables.Append tbl1 Set cati = Nothing
Chuong 3: THIET KE BANG
"Thoát khỏi thủ tục.
TableErrExit:
Exit Sub
TableErrCatcher:
‘Bay 16i “table already exits”.
Xóa bảng và chạy lại thủ tục.
If Err. Number = -2147217857 Then cat1.Tables.Delete "FamilyMembers2"
Resume End If
In chỉ tiết cho các lỗi khác và thoát khỏi thủ tục.
Debug.Print Err.Number, Err.Description Resume TableErrExit
End Sub
Thay Thế Một Bảng
Nếu ứng dụng cơ sở dữ liệu thường xuyên tạo bảng KamiiyMembers2, thủ tục có thé gây ra lỗi "already exists" vào mỗi lân chạy. Trong tình huống này, thủ tục của bạn sẽ chạy nhanh hơn nếu bạn thử xóa bảng đã có sẵn trước khi thêm bảng mới vào. Điều này khắc phục được tình trạng cần phải xử lý lỗi. Bạn vẫn cần trình xử lý lỗi khi một bảng chưa có hoặc khi điều kiện khác gây ra lỗi. Thủ tục dưới đây viết đoạn chương trình xử lý lỗi, bạn đứt khoát xóa một bảng trùng tên với bảng mà bạn muốn nối thêm vào cơ sở đữ liệu.
Sub MakeLocalTableErrCatcher2() On Error GoTo TableErrCatcher Dim cati As ADOX.Catalog Dim tbl1 As ADOX.Table
225 ⁄
'Các đối tượng tham chiếu cho bằng Set cat1 = New Catalog
cat1.ActiveConnection = CurrentProject.Connection Set tbl1 = New Table
‘Dat tén cho bang va các cột nối thêm.
With tbl1
.Name = "FamilyMembers2"
.Columns.Append "Fam!D", adinteger .Columns.Append “Fname", adVarWChar, 20 .Columns.Append “Lname", adVarWChar, 25 .Columns.Append “Relation", adVarWChar, 30 End With
'X6a bang ci (nếu có ở đây).
'Nối thêm một bảng mới và giải phóng tài nguyên.
cat1.Tables.Delete "FamilyMembers2"
cat†1.Tables.Append tbi†
Set cat1 = Nothing
"Thoát khỏi thủ lục.
TableErrExit:
Exit Sub TableErrCatcher:
'Bẫy lỗi "object not in colleclion"(đối tượng không có trong tập hợp).
‘Chay lại chương trình từ dòng tiếp theo.
lf Err.Number = 3265 Then Resume Next
End If
'In các chỉ tiết cho các lỗi khác và thoát khỏi thủ tục.
Debug.Print Err.Number, Err.Description
Chuong 3: THIET KE BANG
Resume TableErrExit End Sub
Số hiệu lỗi 3265 được đề cập tới trong các kết quả của thường ` trình thủ tục xử lý lỗi MakeLocalTobleErrCaetcher2 khi bạn cố xóa một đối tượng không có trong tập hợp. MakeLocalTableErrCatcher2 bẫy lỗi một cách dễ dàng và chương trình bắt đầu lại sau dòng gây ra lỗi đó. Bất kỳ một lỗi nào khác làm cho chương trình kết thúc nhẹ nhàng đều được in số hiệu lỗi và câu diễn giải ra cửa số Immediate.
Làm Việc Với Chỉ Mục
Bạn cũng có thể thêm các khóa chính, các chỉ mục và các mối quan hệ bằng chương trình. Bạn cũng có thể định nghĩa những khúa chớnh và chỉ mục thụng qua một hay nhiều ủeld.
Tạo Một Khóa Chính
Việc thêm một khóa chính hay một chỉ mục vào bảng cũng đơn giản như thêm một bảng mới vào catalog. Đầu tiên bạn tạo một ngữ cảnh để thêm chỉ mục vào đó, nó bao gồm một catalog và một bảng. Thứ hai, bạn định nghĩa các thuộc tính chỉ mục. Những điều này có thể khác nhau giữa chỉ mục và khóa chính. Thứ ba, bạn nối thêm vào cột để tạo chỉ mục rồi nối thêm chỉ mục mới này vào bảng. Nếu có một lỗi xảy ra, ví dụ như chỉ mục đã tồn tại, bạn phải trả lời cho thích hợp. Thủ tục AddPK dưới đây tạo khóa chính một cách linh hoạt.
Sub AddPK()
Dim cati As New ADOX.Catalog Dim tbl1 As New ADOX.Table Dim pki As New ADOX. Index
227
"Tạo một ngữ cảnh cho khóa chính mới.
cat1.ActiveConnection = CurrentProject.Connection Set tbl1 = cat1.Tables(“FamilyMembers2")
‘Cai đặt các thuộc tính của khóa chính.
With pk†
.Name = "MyPrimaryKey"
.PrimaryKey = True Unique = True
.IndexNulls = adIndexNullsDisallow End With
Nối thêm cột vào chỉ mục và nối thêm chỉ mục vào bằng.
pk1.Columns.Append "FamID"
tbl1.Indexes.Append pki 'Giải phóng tài nguyên.
Set cat! = Nothing End Sub
Thủ tục bắt đầu bằng việc khai báo và thuyết minh cho các déi tugng Catalog, Table va Index. (bạn cần ba đối tượng nay dé tao một khóa chính.) Lưu ý rằng không có một đối tượng rõ ràng cho khóa chính. Kế tiếp, thủ tục thiết lập ngữ cảnh cho việc định nghĩa một khóa chính mới Nó thiết lập giá trị cho thuộc tính ActiveConnection cia đối tugng Catalog dé chi đến catalog cha mét cơ sở dữ liệu cụ thể. Rồi nó thiết lập tham chiếu bảng đến một bảng nằm trong cơ sở dữ liệu đó. Tham chiếu này là bảng mà thủ tục của bạn sẽ thêm khóa chính mới vào đó.
Kế tiếp, thủ tục thiết lập bến thuộc tính chỉ mục. Thuộc tính thứ nhất là tên khóa chính. Nó xuất hiện như một mục nhập trong cột Index Name trong cửa sổ Index của bảng đữ liệu. Ba thuộc tính còn lại phân biệt giữa khóa chính và một chỉ mục bình thường. Bạn
Chuong 3: THIET KE BANG
nên luôn luôn thiết lập các thuộc tính này để chúng xuất hiện trong thủ tục AddPK khi bạn tạo một khóa chính.
Thủ tục gọi hai phương pháp Append. Phương pháp thứ nhất nối thờm cột EứmID từ bảng FœmiiyMembers2 vào chỉ mục. Phương pháp thứ hai nối thêm chỉ mục vào bảng. Cuối cùng, thủ tục thiết lập đối tugng Catalog là Nothing, bằng cách này để giải phóng tài nguyên đã dùng tạo khóa chính.
Người ta thường hay sử dụng một ủeld kiểu AutoNumber, Long Integer, hoặc Text làm khóa chính. Các kiểu này nhanh hơn so với một khóa chính của nhiều feld. Tuy nhiên, tại một thời điểm một chỉ mục nhiều ủeld tạo ra tỡnh huống giới hạn việc xỏc định các record duy nhất và trong các giới hạn nào bạn sẽ sử dụng dữ liệu của bảng. Khi một chỉ mục có nhiều khóa thích hợp, bạn có thể nối thêm nhiều cột vào chỉ mục một cách đơn giản trước khi bạn nối chỉ mục vào bảng.
Trong ví dụ trước bạn có thé thay thé dong pk†.Columns.Append "FamlD”
bằng các dòng
pk1.Columns.Append "Lname"
pkt.Columns.Append “Fname"
pk1,Columns.Append "Relation"
Những dòng này định nghĩa một khóa chính vào ba field thay vì chỉ có một. Thủ tục AddPK tạo ra một khóa chính dựa trên một field; trên đỉnh của cửa sổ Indexs trong Hình 3-14 trình bày kết quả của việc gọi hàm AdởPẨ.. Phần dưới của cửa số Index trình bày kết quả việc gọi hàm AdđdPK, nó cũng tương tự như thủ tục AddPK ngoại trừ sự thay thế đoạn mã chương trình như đã chỉ ra ở trên.
(cả hai thủ tục có trong cơ sở dữ liệu của Chương 3 trên CD kèm
229
theo quyển sách này) Bởi vì tại một thời điểm bạn chỉ có thể có duy nhất một khóa chính, do đó bạn phải gỡ bỏ khóa chính bằng tay giữa câu lệnh gọi thủ tục AdởPK và AddPK3.
$ indexes: FamilyMembers2 [xi :
[| Index Name Field Name Sort Order a
FamID Ascending
Index Properties ai
Primary Yes i i
Unique Ignore Nuls = No Yes | The name for this index. Each index can use up to 10 fields. |
# Indexes: FamilyMembers2 :
Index Name Field Name Sort Order
Lname Ascending
Fname Ascending
Relation Ascending
Ti. —... „
Primary Yes re
Unique Ignore Nuis Yes No Ị index can use up to 10 fields. ‡ The name for this index. Each
Hình 3-14. Các cửa sỡ Indexes sau khí chạy thủ lục AddPK và AddPK3.
Thủ tục AddPK và AddPK3 có thể bị sai bởi một số lý do. Hai
lỗi do thủ tục AddPKErr sau đây bấy được là do đã có một khóa chính (số hiệu lỗi là -2147467259) và bảng mở (số hiệu lỗi là -
2147217856). (Như đã nói ở trên, bạn không thể thêm một khéớa 230
Chương 3: THIẾT KẾ BẰNG
chính mới trùng với một khóa đã có; cũng như bạn không thể chỉnh sửa cấu trúc của chỉ mục nếu bảng đang mở.)
Sub AddPKErr() On Error GoTo PKErr
Dim cati As New ADOX.Catalog Dim tbl1 As New ADOX.Table Dim pkt As New ADOX.Index Dim iNumber As Integer
"Tạo một ngữ cảnh cho khóa chính mới.
cat1.ActiveConnection = CurrentProject.Connection Set tbl1 = cat1.Tables("FamilyMembers2")
"Thiết lập các thuộc tính của khóa chính.
'Nhãn (SetPKvariable) cho thủ tục một điểm phục hồi
‘tu’ một khóa chính đã có trước đây.
SetPKvariable:
With pk†
.Name = "MyPrimaryKey"
.PrimaryKey = True .Unique = True
IndexNulls = adindexNulls Disallow End With
'Nối thêm cột vào chỉ mục và nối chỉ mục vào bảng.
pk1.Columns.Append "FamIÐ"
tbl1.lIndexes.Append pk†
'Thoát khỏi thủ tục.
PKErrExit:
Set cat1 = Nothing Exit Sub
PKErr:
231
'Kiểm tra bằng có đang sử dụng hay không lf Err.Number = -2147217856 Then
MsgBox “FamilyMembers2 currently in use. This" & _
“ operation requires the table to be closed.”
'iểm tra đã có khóa chính hay không Elself Err.Number = -2147467259 Then
For Each pk1 tn tbl1.Indexes lf pk1.PrimaryKey = True Then
tbl1.Indexes.Delete (Number) Resume SetPKvariable End If
iNumber = iNumber + 1 Next pk1
'Bẫy các lỗi khác Else
MsgBox "Open Immediate window for Bug report"
Debug.Print Err.Number; Err.Description Resume PKErrExit
End ff End Sub
Có một số ngoại lệ trong việc bãy lỗi, thủ tuc AddPKErr theo logic của thủ tục AddPK trong phân ¿oạn chính của nó. Đầu tiên thủ tục AddPKErr cho phép một thường trình xử lý lỗi bằng câu lénh On Error. Ving khai báo bao gồm một câu lệnh Dim mới cho một biến kiểu Integer. Trình xử lý lỗi dùng biến này như là một chỉ mục trong vòng lặp để lặp đi lặp lại qua các tập chỉ mục trong bảng.
Trình xử lý lỗi logic trong thủ tục AddPKErr bắt đầu từ nhãn PKErr. Một cõu lệnh ùƒ..Then kiểm tra xem bảng cú mở hay khụng.
Nếu mở, thường trình thủ tục hiển thị một hộp thông báo diễn giải sự trục trặc và đưa ra cách giải quyết trước khi thoát một cách êm
Chuong 3: THIET KE BANG
a. Mệnh dé ElseIf phát hiện sự hiện hữu của khóa chính. Trong trường hợp này, chương trình sẽ đếm những chỉ mục trong bảng cho đến khi nó nhận ra khóa chính bằng cách xem giá trị của thuộc tính PrưnaryRey có là True hay không. Nếu đúng, nó sẽ xóa chỉ mục đó và trả điều khiển về điểm khởi tạo một khóa chính mới.
Đây là điều cân thiết vì lỗi sẽ xóa sạch các cài đặt trước đó. Nếu bảng dữ liệu không mở và không có khóa chính tổn tại, thường trình thủ tục sẽ hiện thị số hiệu lỗi và câu diễn giải ra cửa sổ Immediate trước khi thoát khỏi thủ tục. Hộp thông báo chỉ cho người dùng xem nguyên nhân gây ra lỗi trong cửa số Immediate.
Tạo Một Chỉ Mục
Việc thêm một chỉ mục vào bảng không khác nhiều so với việc thêm một khóa chính. Điểm khác biệt chủ yếu là không thiết lập thuộc tính PrimaryKey la True. (gia tri False la gia tri mac nhién). Tha tue AddJdx duéi day duge thiét kế giống như thủ tục AddPK Ngoài sự khác nhau là không cài đặt thuộc tính của khóa chính ra, sự khác nhau chủ yếu là do ấn định một thứ tự sắp xếp rõ ràng cho chỉ mục. Bằng cách chỉ dẫn cho bảng sắp xếp các giá trị cột FamID theo thứ tự giảm dần, thủ tục tạo sự trình bày của bảng trước hết là những record gần đây nhất (thừa nhận các record có giá trị FamID cao hơn được thêm vào sau các giá trị trước đó). Khi ấn định thứ tự sắp xếp, bạn phải chỉ định số hiệu cột. Việc đánh số cho các cột bắt đầu là 0 cho cột đầu tiên.
Sub Addidx()
Dim cati As New ADOX.Catalog Dim tbl1 As New ADOX.Table Dim idx1 As New ADOX. Index
'Tạo ngữ cảnh cho chỉ mục mới.
cat1.ActiveConnection = CurrentProject.Connection
233