Về bài hướng dẫn này Hướng dẫn này trình bày: Các thẻ điều khiển handle môi trường, kết nối, câu lệnh và bộ mô tả descriptor là gì và các ứng dụng CLI/ODBC được sử dụng như thế nào..
Trang 1Chuẩn bị cho Kỳ thi 733 về Phát triển ứng dụng DB2 9, Phần 5: Lập trình
CLI/ODBC
Roger Sanders, Quản lý cao cấp, EMC
Tóm tắt: Hướng dẫn này giới thiệu cho bạn về lập trình DB2 CLI (Call-Level
Interface - giao diện mức gọi)/lập trình ODBC và dẫn bạn qua các bước cơ bản được sử dụng để xây dựng một ứng dụng CLI/ODBC Hướng dẫn này cũng giới thiệu cho bạn quá trình sử dụng để chuyển đổi một hoặc nhiều tệp tin mã nguồn của ngôn ngữ lập trình bậc cao có chứa các lời gọi hàm CLI/ODBC thành một ứng dụng sẵn sàng để chạy Đây là hướng dẫn thứ năm trong một loạt bài gồm chín hướng dẫn được thiết kế để giúp bạn chuẩn bị cho kỳ thi lấy chứng chỉ Nhà phát triển ứng dụng DB2 UDB V9.1 (kỳ thi 733)
Trước khi bạn bắt đầu
Tìm hiểu bạn mong đợi những gì từ hướng dẫn này và làm thế nào để thu nhận được nhiều nhất từ nó
Về loạt bài viết này
Chức danh Nhà phát triển ứng dụng được IBM chứng nhận khẳng định rằng bạn là một nhà phát triển ứng dụng mức trung cấp hoặc cao cấp về DB2 với Linux®, UNIX® và Windows® Chứng chỉ này cũng chứng tỏ rằng bạn có các kỹ năng giỏi trong tất cả các nhiệm vụ lập trình chung cũng như lập trình SQL có nhúng, lập trình ODBC/CLI, lập trình NET hoặc lập trình Java
Loạt bài gồm chín hướng dẫn miễn phí này được thiết kế để giúp bạn chuẩn bị cho
kỳ thi lấy chứng chỉ Phát triển ứng dụng DB2 9 cho Linux, UNIX và Windows (kỳ thi 733) Mỗi hướng dẫn bao gồm một liên kết đến một bản tải về dùng thử miễn phí DB2 9 cho Linux, UNIX và Windows Các hướng dẫn này cung cấp một cơ sở
Trang 2vững chắc cho mỗi phần của kỳ thi Tuy nhiên, bạn không nên dựa vào các hướng dẫn này như là sự chuẩn bị duy nhất của bạn cho kỳ thi này
Sau khi đăng ký một cách nhanh chóng, bạn có thể bắt đầu một hướng dẫn Mỗi hướng dẫn cần khoảng một giờ để hoàn thành Bạn có thể sử dụng hướng dẫn trực tuyến, hoặc tải xuống một tệp tin PDF hoặc zip
Về bài hướng dẫn này
Hướng dẫn này trình bày:
Các thẻ điều khiển (handle) môi trường, kết nối, câu lệnh và bộ mô tả
(descriptor) là gì và các ứng dụng CLI/ODBC được sử dụng như thế nào
Các bước cần có trong việc phát triển một ứng dụng CLI/ODBC
Trình tự đúng đắn cần sử dụng khi gọi các hàm CLI/ODBC
Làm thế nào để thiết lập một kết nối cơ sở dữ liệu từ một ứng dụng
CLI/ODBC
Làm thế nào để cấu hình một trình điều khiển CLI/ODBC
Làm thế nào để đánh giá các mã trả về của hàm CLI/ODBC và nhận được thông tin chẩn đoán khi các lỗi xuất hiện
Làm thế nào để chuyển đổi các tệp tin mã nguồn có chứa các lời gọi
CLI/ODBC thành một ứng dụng sẵn sàng để chạy
Trang 3Đây là bài thứ năm trong một loạt bài gồm chín hướng dẫn được thiết kế để giúp bạn chuẩn bị cho kỳ thi lấy chứng chỉ Nhà phát triển ứng dụng DB2 V9.1 (kỳ thi 733) Tư liệu trong hướng dẫn này trình bày các mục tiêu trong Phần 5 của kỳ thi, mang tên "Lập trình CLI/ODBC"
Các mục tiêu
Sau khi hoàn thành hướng dẫn này, bạn sẽ có thể:
Thiết lập một kết nối cơ sở dữ liệu trong một ứng dụng CLI/ODBC
Thi hành các yêu cầu SQL bằng cách gọi các hàm CLI/ODBC trong một trình tự phù hợp
Phân tích các kết quả và xử lý các lỗi thường gặp khi các hàm CLI/ODBC được gọi trong một ứng dụng CLI/ODBC
Các điều kiện cần trước
Để hiểu một số tư liệu được trình bày trong hướng dẫn này, bạn cần phải đã quen thuộc với những thuật ngữ sau đây:
Đối tượng: Mọi thứ trong một cơ sở dữ liệu có thể được tạo ra hoặc được
thao tác bằng SQL (ví dụ như các bảng, các khung nhìn, các chỉ mục và các gói)
Trang 4 Bảng: Một cấu trúc logic được sử dụng để trình bày dữ liệu như là một tập
hợp các hàng không theo thứ tự với một số các cột cố định Mỗi cột có chứa một
bộ các giá trị, mỗi giá trị của cùng một kiểu dữ liệu (hoặc một kiểu con của kiểu
dữ liệu cột); các định nghĩa về các cột tạo thành cấu trúc bảng và các hàng chứa các dữ liệu bảng thực tế
Trình tối ưu hóa DB2: Một thành phần của trình tiền biên dịch
(precompiler) SQL chọn một kế hoạch truy cập cho một câu lệnh SQL của Data Manipulation Language (DML - Ngôn ngữ thao tác dữ liệu) bằng cách mô hình hóa chi phí thi hành của một số kế hoạch truy cập thay thế được cho nhau và lựa chọn kế hoạch có chi phí ước tính thấp nhất
Các yêu cầu hệ thống
Bạn không cần phải dùng một bản sao của Cơ sở dữ liệu đa năng DB2 để hoàn thành hướng dẫn này Tuy nhiên, bạn có thể tải về một phiên bản dùng thử miễn phí của Cơ sở dữ liệu đa năng DB2 IBM, Ấn bản doanh nghiệp (IBM DB2
Trang 5và lấy ra các dữ liệu của SQL Một số phương pháp có sẵn để kết hợp SQL với một ngôn ngữ lập trình bậc cao, nhưng cách tiếp cận đơn giản nhất là nhúng các câu lệnh SQL trực tiếp vào các tệp tin mã nguồn của ngôn ngữ lập trình bậc cao đã được sử dụng để tạo ra ứng dụng Kỹ thuật này được gọi là lập trình SQL nhúng
Một trong những mặt hạn chế lớn nhất với việc lập trình SQL nhúng là thiếu khả năng tương tác mà các ứng dụng như vậy cần phải có; các ứng dụng SQL nhúng được phát triển dành riêng cho DB2 phải được sửa đổi (và trong một số trường hợp, được viết lại hoàn toàn) trước khi chúng có thể tương tác với các hệ thống quản lý cơ sở dữ liệu quan hệ (RDBMS) khác Bởi vì hạn chế này tồn tại với mọi ứng dụng SQL nhúng, bất kể nó được viết cho RDBMS nào, trong đầu những năm
1990 công ty X/Open và SQL Access Group (SAG - Nhóm truy cập SQL) bây giờ
là một phần của công ty X/Open, đã cùng nhau phát triển một đặc tả tiêu chuẩn cho một giao diện SQL có thể gọi được Giao diện này được gọi là giao diện X/Open CLI Nhiều đặc tả kỹ thuật X/Open CLI sau đó được chấp nhận như là một phần của chuẩn quốc tế ISO CLI Mục đích chính của X/Open CLI đã là để làm tăng tính di động của các ứng dụng cơ sở dữ liệu bằng cách cho phép chúng trở thành độc lập với bất kỳ giao diện lập trình của một hệ thống quản lý cơ sở dữ liệu nào
Trong năm 1992, Microsoft đã phát triển một giao diện SQL có thể gọi được có tên là Open Database Connectivity (ODBC - Kết nối cơ sở dữ liệu mở) dành cho
hệ điều hành Windows của Microsoft Trên cơ sở đặc tả kỹ thuật tiêu chuẩn
X/Open CLI, ODBC cung cấp các chức năng và các khả năng mở rộng không phải
là một phần X/Open CLI ODBC dựa vào một môi trường vận hành trong đó các trình điều khiển ODBC đặc thù cho từng nguồn dữ liệu được tự động nạp vào trong thời gian chạy ứng dụng (dựa trên thông tin được cung cấp khi yêu cầu một kết nối) bằng một thành phần được gọi là Trình quản lý trình điều khiển ODBC (ODBC Driver Manager) Mỗi trình điều khiển đặc thù cho một nguồn dữ liệu có
Trang 6trách nhiệm triển khai thực hiện bất kỳ hoặc tất cả các hàm được định nghĩa trong đặc tả kỹ thuật ODBC và chịu trách nhiệm cung cấp các tương tác với nguồn dữ liệu mà trình điều khiển đã được viết cho nó Trình quản lý trình điều khiển
ODBC cung cấp một điểm kiểm soát trung tâm; khi một ứng dụng ODBC thi hành, mỗi lời gọi hàm ODBC đã thực hiện được gửi đến Trình quản lý trình điều khiển ODBC, ở đó nó được chuyển tiếp đến trình điều khiển của nguồn dữ liệu thích hợp để tiếp tục xử lý Với các trình điều khiển, một ứng dụng được liên kết trực tiếp đến chỉ một thư viện trình điều khiển ODBC, chứ không phải đến chính mỗi cơ sở dữ liệu sản phẩm cụ thể
DB2 CLI cũng dựa trên tiêu chuẩn quốc tế ISO CLI và nó cung cấp hầu hết tính năng được tìm thấy trong đặc tả kỹ thuật ODBC Các ứng dụng có sử dụng DB2 CLI thay vì ODBC được liên kết trực tiếp với thư viện nạp DB2 CLI và bất kỳ Trình quản lý trình điều khiển ODBC nào có thể nạp thư viện này như là một trình điều khiển ODBC Các ứng dụng DB2 UDB cũng có thể sử dụng thư viện nạp DB2 CLI độc lập Tuy nhiên, khi thư viện được sử dụng theo cách này, bản thân ứng dụng không có khả năng giao tiếp với các nguồn dữ liệu khác
Sự khác nhau giữa SQL nhúng và CLI/ODBC
Trong hướng dẫn thứ tư của loạt bài này (xem phần Tài nguyên), bạn đã thấy rằng các ứng dụng SQL nhúng được xây dựng bằng cách nhúng trực tiếp các câu lệnh SQL vào trong một hay nhiều tệp tin mã nguồn được viết bằng ngôn ngữ lập trình bậc cao Ứng dụng CLI/ODBC, mặt khác, dựa vào một bộ chuẩn hóa các hàm giao diện lập trình ứng dụng (API) để gửi các câu lệnh SQL tới Trình quản lý cơ sở dữ liệu DB2 để xử lý Các ứng dụng có SQL nhúng và các ứng dụng CLI/ODBC cũng khác theo các cách sau đây:
Trang 7 Các ứng dụng CLI/ODBC không yêu cầu khai báo tường minh và sử dụng biến chủ chứa; bất kỳ biến nào có thể được sử dụng để gửi dữ liệu tới hoặc lấy ra
dữ liệu từ một nguồn dữ liệu
Các con trỏ không cần phải được các ứng dụng CLI/ODBC khai báo tường minh Thay vào đó, các con trỏ được tự động tạo ra, nếu cần thiết, bất cứ khi nào hàm SQLExecute() hay hàm SQLExecDirect() được thi hành (Hai hàm này được trình bày chi tiết hơn sau đây một chút)
Các con trỏ không cần phải được mở tường minh trong các ứng dụng
CLI/ODBC; các con trỏ ngầm ẩn là được mở ngay sau khi chúng được tạo ra
Các hàm CLI/ODBC quản lý môi trường, kết nối và thông tin liên quan đến
câu lệnh SQL bằng cách sử dụng các thẻ điều khiển (handles) Kỹ thuật này cho
phép các thông tin như vậy được xử lý như là các đối tượng trừu tượng Việc sử dụng các thẻ điều khiển loại bỏ sự cần thiết đối với các ứng dụng CLI/ODBC phải
sử dụng các cấu trúc dữ liệu đặc thù riêng của sản phẩm cơ sở dữ liệu, chẳng hạn như các cấu trúc dữ liệu DB2 SQL Communications Area (SQLCA – Vùng trao đổi thông tin SQL DB2) và SQL Descriptor Area (SQLDA – Vùng bộ mô tả SQL)
Các ứng dụng CLI/ODBC vốn đã có khả năng thiết lập nhiều kết nối tới nhiều nguồn dữ liệu hoặc tới cùng một nguồn dữ liệu, cùng một lúc (Các ứng dụng SQL nhúng chỉ có thể kết nối với nhiều nguồn dữ liệu cùng một lúc, nếu sử dụng kết nối Kiểu 2)
Bất kể các sự khác biệt này, có một khái niệm quan trọng chung cho cả các ứng dụng SQL nhúng lẫn các ứng dụng CLI/ODBC: các ứng dụng CLI/ODBC có thể thi hành bất kỳ câu lệnh SQL nào có thể được chuẩn bị động trong một ứng dụng SQL nhúng Điều này được đảm bảo bởi vì các ứng dụng CLI/ODBC chuyển tất
cả các câu lệnh SQL của mình trực tiếp vào nguồn dữ liệu để thi hành động (Các
Trang 8ứng dụng CLI/ODBC cũng có thể thi hành một số các câu lệnh SQL mà chúng không thể được chuẩn bị động, chẳng hạn như các câu lệnh SQL phức hợp, nhưng đối với hầu hết các phần, SQL tĩnh không được hỗ trợ)
Bởi vì nguồn dữ liệu xử lý tất cả các các câu lệnh SQL được một ứng dụng
CLI/ODBC đề trình, tính khả chuyển của các ứng dụng CLI/ODBC được đảm bảo Điều này không phải luôn đúng với các ứng dụng SQL nhúng, bởi vì cách thức mà các câu lệnh SQL được chuẩn bị động có thể khác nhau với mỗi sản phẩm
cơ sở dữ liệu quan hệ được sử dụng Hơn nữa, do các câu lệnh SQL COMMIT và ROLLBACK có thể được một số sản phẩm cơ sở dữ liệu (bao gồm cả DB2) chuẩn
bị động nhưng những sản phẩm cơ sở dữ liệu khác lại không làm được như vậy, chúng thường không được sử dụng trong ứng dụng CLI/ODBC Thay vào đó, các ứng dụng CLI/ODBC dựa vào hàm SQLEndTran() để chấm dứt các giao dịch hoạt động (khi không sử dụng cam kết tự động) Điều này đảm bảo rằng ứng dụng CLI/ODBC có thể kết thúc giao dịch thành công, bất kể sản phẩm cơ sở dữ liệu nào đang được sử dụng
Việc xây dựng một ứng dụng CLI/ODBC
Trang 9Công việc kết hợp với mỗi một trong các nhiệm cụ này được tiến hành bằng cách gọi ra một hay nhiều hàm API CLI/ODBC; nhiều hàm CLI/ODBC được sử dụng
để thực hiện các nhiệm vụ này phải được gọi theo một thứ tự cụ thể hoặc nếu không một lỗi xuất hiện Hình 1 xác định một số các hàm CLI/ODBC cơ bản được
sử dụng để thực hiện các nhiệm vụ khởi tạo và kết thúc:
Hình 1 Một ứng dụng CLI/ODBC thực hiện các nhiệm vụ cơ bản
Các ứng dụng CLI/ODBC có thể thực hiện các nhiệm vụ khác với ba nhiệm vụ phác thảo trong Hình 1, như là xử lý lỗi và xử lý thông báo Một phần sau đây, các
Trang 10chẩn đoán và xử lý lỗi (Diagnostics and error handling), cho thấy các lỗi được xử
lý trong một ứng dụng CLI/ODBC như thế nào
Cấp phát tài nguyên
Trong thời gian khởi tạo, các tài nguyên cần thiết để xử lý các giao dịch được cấp phát (và được khởi tạo) và kết nối vào bất kỳ (các) nguồn dữ liệu nào mà các tương tác của nhiệm vụ xử lý giao dịch được thiết lập với nguồn dữ liệu đó Các tài nguyên được các ứng dụng CLI/ODBC sử dụng bao gồm các vùng lưu trữ dữ liệu đặc biệt được xác định bằng các thẻ điều khiển duy nhất (Một thẻ điều khiển chỉ đơn giản là một biến con trỏ trỏ đến một đối tượng dữ liệu được Trình quản lý trình điều khiển DB2 CLI hoặc ODBC kiểm soát và được các lời gọi hàm
CLI/ODBC tham chiếu) Bằng cách sử dụng các vùng lưu trữ dữ liệu và các thẻ điều khiển, các ứng dụng CLI/ODBC được giải phóng khỏi trách nhiệm cấp phát
và quản lý các biến và cấu trúc dữ liệu toàn cục như các cấu trúc dữ liệu SQLCA
và SQLDA được sử dụng với các ứng dụng SQL nhúng Bốn kiểu thẻ điều khiển khác nhau có sẵn:
Các thẻ điều khiển môi trường: Một con trỏ tới một vùng lưu trữ dữ liệu
chứa thông tin đặc thù CLI/ODBC, là thông tin toàn cục về bản chất
Các thẻ điều khiển kết nối: Một con trỏ tới một vùng lưu trữ dữ liệu có
chứa thông tin về một kết nối nguồn dữ liệu (cơ sở dữ liệu) được CLI/ODBC quản
lý
Các thẻ điều khiển câu lệnh: Một con trỏ tới một vùng lưu trữ dữ liệu có
chứa thông tin cụ thể về một câu lệnh SQL
Trang 11 Các thẻ điều khiển bộ mô tả: Một con trỏ tới một vùng lưu trữ dữ liệu có
chứa một tập hợp các siêu dữ liệu có mô tả hoặc các biến ứng dụng đã được kết buộc với các đánh dấu tham số trong một câu lệnh SQL hoặc các biến ứng dụng đã được kết buộc với các cột của một bộ dữ liệu kết quả, đã được tạo ra để đáp lại một truy vấn
Mỗi ứng dụng CLI/ODBC phải bắt đầu bằng cách cấp phát một thẻ điều khiển môi trường Thông thường chỉ một thẻ điều khiển môi trường được cấp phát cho mỗi ứng dụng và thẻ điều khiển đó phải tồn tại trước khi bất kỳ thẻ điều khiển nào khác có thể được cấp phát; tất cả các thẻ điều khiển khác được quản lý trong bối cảnh của thẻ điều khiển môi trường được sử dụng Các thẻ điều khiển môi trường được cấp phát bằng cách gọi hàm SQLAllocHandle() với tùy chọn
SQL_HANDLE_ENV được chỉ rõ Mã nguồn được sử dụng để cấp phát một thẻ điều khiển môi trường trông giống như thế này:
Trang 12tới bất kỳ nguồn dữ liệu nào có thể được thiết lập Các thẻ điều khiển kết nối được cấp phát bằng cách gọi hàm SQLAllocHandle() dùng tùy chọn
SQL_HANDLE_DBC và một thẻ điều khiển môi trường hợp lệ được chỉ rõ Mã nguồn được sử dụng để cấp phát một thẻ điều khiển kết nối trông giống như sau:
Trang 13 Nhận siêu dữ liệu về bất kỳ các bộ dữ liệu kết quả nào được tạo ra để đáp lại một câu lệnh SQL
Kết buộc các biến ứng dụng tới các cột có trong bất kỳ các bộ dữ liệu kết quả đã tạo ra
Lấy ra (tìm nạp) dữ liệu từ bất kỳ bộ dữ liệu kết quả nào được tạo ra
Nhận các thông tin chẩn đoán khi một câu lệnh SQL không thi hành được
Mỗi câu lệnh SQL được mã hóa trong một ứng dụng CLI/ODBC phải có thẻ điều khiển câu lệnh riêng của nó Và mỗi thẻ điều khiển câu lệnh được sử dụng chỉ có thể được kết hợp với một thẻ điều khiển kết nối Tuy nhiên, bất kỳ số lượng các thẻ điều khiển câu lệnh nào cũng có thể được kết hợp với một thẻ điều khiển kết nối Các thẻ điều khiển câu lệnh được cấp phát bằng cách gọi hàm
SQLAllocHandle() dùng tùy chọn SQL_HANDLE_STMT và thẻ điều khiển kết nối hợp lệ được chỉ rõ Vì vậy, mã nguồn được sử dụng để cấp phát một thẻ điều khiển câu lệnh trông giống như sau:
Trang 14
Bất cứ khi nào một thẻ điều khiển câu lệnh được cấp phát, bốn thẻ điều khiển bộ
mô tả sẽ tự động được cấp phát và được kết hợp với thẻ điều khiển câu lệnh như là một phần của quá trình cấp phát Sau khi được cấp phát, các thẻ điều khiển bộ mô
tả này vẫn giữ nguyên kết hợp với thẻ điều khiển câu lệnh tương ứng cho đến khi
nó bị hủy bỏ (và lúc đó các thẻ điều khiển bộ mô tả cũng bị hủy bỏ) Hầu hết các hoạt động CLI/ODBC có thể được thực hiện bằng cách sử dụng các thẻ điều khiển
bộ mô tả được định nghĩa ngầm ẩn này Tuy nhiên, có thể cấp phát tường minh một hoặc nhiều thẻ điều khiển bộ mô tả khi gọi hàm SQLAllocHandle() dùng tùy chọn SQL_HANDLE_DESC và thẻ điều khiển kết nối hợp lệ được định rõ
Khai báo phiên bản CLI/ODBC của ứng dụng
Cả hai CLI và ODBC sử dụng trình điều khiển đặc thù theo sản phẩm để giao tiếp với các nguồn dữ liệu (cơ sở dữ liệu) và hầu hết các trình điều khiển này có chứa một bộ các tham số động, có thể được sửa đổi để thay đổi hành vi của trình điều khiển để đáp ứng nhu cầu của ứng dụng Các tham số này được nói đến như là các thuộc tính và tất cả các thẻ điều khiển môi trường, kết nối và câu lệnh được cấp phát có một bộ thuộc tính riêng của mình (Một phần dưới đây mô tả các hàm CLI/ODBC được sử dụng để lấy ra và sửa đổi các thuộc tính kết hợp với một thẻ điều khiển môi trường, kết nối hoặc câu lệnh) Một thuộc tính môi trường như vậy
là thuộc tính SQL_ATTR_ODBC_VERSION, nó phải được gán giá trị
SQL_OV_ODBC3 hoặc SQL_OV_ODBC2 sau khi một thẻ điều khiển môi trường
Trang 15được cấp phát, nhưng trước khi các thẻ điều khiển kết nối tương ứng được cấp phát Điều này báo cho DB2 CLI và Trình quản lý trình điều khiển ODBC rằng ứng dụng dự định tuân thủ hoặc đặc tả kỹ thuật CLI/ODBC 3.x hoặc đặc tả kỹ thuật CLI/ODBC 2.0 (hoặc cũ hơn) Mã nguồn được sử dụng để thông báo cho DB2 CLI và trình điều khiển ODBC rằng một ứng dụng dự định tuân thủ đặc tả kỹ thuật CLI/ODBC 3.x (hoặc mới hơn) trông giống như sau:
Trang 16
Thiết lập một kết nối nguồn dữ liệu (cơ sở dữ liệu)
Để thực hiện bất kỳ kiểu hoạt động nào đối với một cơ sở dữ liệu, trước tiên bạn phải thiết lập một kết nối với cơ sở dữ liệu đó Với các ứng dụng CLI/ODBC, ba hàm khác nhau có thể được dùng để thiết lập một kết nối nguồn dữ liệu (cơ sở dữ liệu):
SQLGetInfo() chỉ rõ kiểu thông tin SQL_MAX_DRIVER_CONNECTIONS để tìm ra có bao nhiêu kết nối hoạt động mà một nguồn dữ liệu cụ thể hỗ trợ)
Hàm SQLConnect() là một hàm kết nối CLI/ODBC đơn giản nhất có sẵn Khi được sử dụng, hàm SQLConnect() giả định rằng thông tin duy nhất cần thiết để thiết lập một kết nối là một tên nguồn dữ liệu và tùy trường hợp, một mã nhận dạng ID (mã nhận dạng quyền hạn ID) và mật khẩu của người sử dụng (Tất cả các thông tin cần thiết khác được lưu trữ trong phần [COMMON] của tệp tin
db2cli.ini, phần [ODBC] của tệp tin ODBC.INI hoặc khóa phụ ODBC trong phần đăng ký hệ thống) Hàm này hoạt động tốt với các ứng dụng cần kết nối với các nguồn dữ liệu mà chỉ yêu cầu một mã nhận dạng người sử dụng và mật khẩu và với các ứng dụng muốn cung cấp giao diện kết nối riêng của chúng hoặc không đòi hỏi giao diện người dùng nào
Trang 17Hàm SQLDriverConnect(), mặt khác, cho phép một ứng dụng gửi thông tin kết nối tới một trình điều khiển nguồn dữ liệu bằng cách sử dụng một chuỗi ký tự kết nối (đối lập với việc lưu trữ các thông tin này trong tệp tin db2cli.ini, tệp ODBC.INI hoặc đăng ký hệ thống và cho phép các trình điều khiển lấy nó ra) Một chuỗi kết nối chỉ đơn giản là một loạt các cặp từ khóa/giá trị, được phân tách bằng các dấu chấm phẩy (;), có chứa các thông tin được sử dụng để thiết lập một kết nối đến một nguồn dữ liệu Bảng 1 chỉ ra một số các cặp từ khoá/giá trị thường hay được
sử dụng
Bảng 1 Các cặp từ khoá/giá trị được sử dụng với SQLDriverConnect()
Từ khoá/giá trị Mục đích
DRIVER=DriverName Chỉ rõ tên của trình điều khiển CLI/ODBC được sử
dụng để thiết lập một kết nối đến một nguồn dữ liệu
DBALIAS=DatabaseAlias Chỉ rõ bí danh của một cơ sở dữ liệu mà kết nối được
thiết lập với nó
DSN=DataSourceName
Chỉ rõ tên của một nguồn dữ liệu (khi được hàm SQLDataSources() trả về) mà một kết nối được thiết lập với nó
UID=UserID Chỉ rõ ID người dùng (ID được cấp quyền) của người
sử dụng đang cố gắng để thiết lập kết nối đó
Trang 18PWD=Password
Chỉ rõ mật khẩu tương ứng với ID người dùng (ID được cấp quyền) đã xác định Nếu một mật khẩu không phải là bắt buộc đối với ID người dùng cụ thể, một chuỗi mật khẩu rỗng (PWD=;) sẽ được sử dụng
NEWPWD=NewPassword
Chỉ rõ mật khẩu mới sẽ được gán cho ID người sử dụng (ID được cấp quyền) cụ thể Nếu từ khóa NEWPWD được sử dụng nhưng không có mật khẩu mới được tạo ra (NEWPWD=;), trình điều khiển DB2 CLI nhắc người sử dụng tạo ra một mật khẩu mới
Như vậy, mã nguồn được sử dụng để thiết lập một kết nối đến một cơ sở dữ liệu
đã ghi vào danh mục có tên là PAYROLL, khi sử dụng ID được cấp quyền là db2admin và mật khẩu tương ứng ibmdb2 dùng hàm SQLDriverConnect() sẽ trông giống như sau:
Trang 19Khi được gọi ra, hàm SQLDriverConnect() phân tích cú pháp chuỗi kết nối được cung cấp và bằng cách sử dụng tên nguồn dữ liệu đã chỉ rõ, cố gắng để lấy ra thông tin bổ sung cần thiết từ hệ thống để thiết lập một kết nối Sử dụng thông tin này, sau đó hàm đăng nhập vào máy chủ phù hợp và cố gắng kết nối với nguồn dữ liệu đã chỉ định Các ứng dụng sử dụng hàm SQLDriverConnect() cũng có thể cho phép trình điều khiển nhắc người sử dụng về bất kỳ thông tin kết nối nào cần thiết
Ví dụ, khi hàm SQLDriverConnect() được gọi với một chuỗi kết nối rỗng, DB2 CLI sẽ hiển thị một hộp thoại và nhắc người sử dụng:
1 Chọn một nguồn dữ liệu từ một danh sách các nguồn dữ liệu đã được DB2 CLI nhận biết
Trang 202 Cung cấp một ID của người dùng cùng với một mật khẩu tương ứng
3 Chỉ rõ xem chế độ kết nối được sử dụng là dành riêng hoặc được dùng chung
Việc hộp thoại này có hiển thị hay không được xác định bởi một trong các giá trị tham số được chuyển tới hàm SQLDriverConnect() Nếu hàm này được gọi với tùy chọn được chỉ rõ là SQL_DRIVER_PROMPT, SQL_DRIVER_COMPLETE hoặc SQL_DRIVER_COMPLETE_REQUIRED hộp thoại sẽ được hiển thị nếu chuỗi kết nối đã cung cấp không chứa đủ thông tin để thiết lập một kết nối nguồn
dữ liệu Mặt khác, nếu hàm này được gọi với tùy chọn được chỉ rõ là
SQL_DRIVER_NOPROMPT nhưng cần nhiều thông tin hơn, một lỗi sẽ được trả
về
Cũng giống như hàm SQLDriverConnect(), hàm SQLBrowseConnect() sử dụng một chuỗi kết nối để gửi thông tin kết nối đến một trình điều khiển Tuy nhiên, hàm SQLDriverConnect() đòi hỏi một chuỗi kết nối hợp lệ trong thời gian biên dịch, còn hàm SQLBrowseConnect() có thể được sử dụng để xây dựng một chuỗi kết nối trong thời gian chạy ứng dụng Sự khác biệt này cho phép một ứng dụng sử dụng hộp thoại riêng của mình để nhắc người sử dụng cung cấp các thông tin kết nối, do đó duy trì quyền kiểm soát dáng vẻ của ứng dụng
Xử lý giao dịch
Sau khi một ứng dụng CLI/ODBC thực hiện việc khởi tạo thích hợp, sự chú ý chuyển tới việc xử lý các giao dịch Đây là nơi mà các câu lệnh SQL truy vấn và thao tác dữ liệu được chuyển tới nguồn dữ liệu thích hợp (trong trường hợp của
Trang 21chúng ta, thường là một cơ sở dữ liệu DB2) bằng các cuộc gọi hàm CLI/ODBC để
xử lý Trong quá trình xử lý giao dịch, một ứng dụng CLI/ODBC thực hiện năm bước sau đây, theo thứ tự trình bày:
1 Cấp phát một hoặc nhiều thẻ điều khiển câu lệnh
2 Chuẩn bị và thực hiện một hoặc nhiều câu lệnh SQL
3 Lấy ra và xử lý bất kỳ kết quả nào được tạo ra
4 Chấm dứt giao dịch hiện tại bằng cách cam kết nó hoặc khôi phục lại nó (rolling it back)
5 Giải phóng tất cả các thẻ điều khiển câu lệnh được cấp phát
Hình 2 chỉ ra các bước cơ bản được thực hiện trong nhiệm vụ xử lý giao dịch và nhận biết các cuộc gọi hàm CLI/ODBC thường được sử dụng để thi hành từng bước:
Trang 22Hình 2 Xử lý các giao dịch trong một ứng dụng CLI/ODBC
Cấp phát các thẻ điều khiển câu lệnh
Một thẻ điều khiển câu lệnh là nói về một đối tượng dữ liệu có chứa các thông tin
về một câu lệnh SQL Thông tin này bao gồm:
Trang 23 Văn bản của câu lệnh SQL
Các chi tiết về con trỏ (nếu có), có kết hợp với câu lệnh
Các kết buộc với tất cả các biến dấu tham số của câu lệnh SQL
Các kết buộc với các biến cột dữ liệu của bộ dữ liệu kết quả
Mã trả về khi thi hành câu lệnh
Thông tin trạng thái
Các thẻ điều khiển câu lệnh SQL được cấp phát bằng cách gọi hàm
SQLAllocHandle() với tùy chọn SQL_HANDLE_STMT và một thẻ điều khiển kết nối hợp lệ được chỉ rõ Ít nhất, một thẻ điều khiển câu lệnh phải được cấp phát trước khi bất kỳ các câu lệnh SQL nào có thể được một ứng dụng CLI/ODBC thực hiện
Chuẩn bị và thực hiện các câu lệnh SQL
Sau khi một thẻ điều khiển câu lệnh được cấp phát và một câu lệnh SQL được gán tới nó, có hai cách theo đó chính câu lệnh SQL có thể được xử lý:
Chuẩn bị và thi hành: Cách tiếp cận này phân tách việc chuẩn bị câu lệnh
SQL khỏi việc thi hành nó và thường được sử dụng khi một câu lệnh SQL cần được thi hành lặp lại nhiều lần Bạn cũng có thể sử dụng phương pháp này khi một ứng dụng cần các thông tin trước về các cột sẽ có mặt trong các bộ dữ liệu kết quả được tạo ra khi thi hành một câu lệnh SQL Các hàm CLI/ODBC là SQLPrepare()
và SQLExecute() được sử dụng để xử lý các câu lệnh SQL theo cách này
Trang 24 Thi hành ngay lập tức: Cách tiếp cận này kết hợp việc chuẩn bị và việc
thực hiện một câu lệnh SQL thành chỉ một bước và thường được sử dụng khi một câu lệnh SQL cần được thi hành chỉ một lần Bạn cũng có thể sử dụng cách tiếp cận này khi các ứng dụng không cần các thông tin bổ sung về bất kỳ bộ dữ liệu kết quả được tạo ra khi câu lệnh SQL được thi hành Hàm SQLExecDirect() được sử dụng để xử lý câu lệnh SQL theo cách này
Cả hai phương pháp này cho phép sử dụng các dấu tham số thay cho các hằng số
và các biểu thức trong câu lệnh SQL đang được xử lý Các dấu tham số được biểu diễn bởi ký tự dấu hỏi (?) và chúng chỉ thị vị trí trong câu lệnh SQL ở đó giá trị hiện tại của một hoặc nhiều biến ứng dụng được thay thế khi câu lệnh được thi hành Khi một biến ứng dụng được kết hợp với một dấu tham số cụ thể trong một câu lệnh SQL, thì biến này được gọi là đã "kết buộc" với dấu tham số đó Việc kết buộc như vậy được thực hiện bằng cách gọi hàm SQLBindParameter() và sau khi một biến ứng dụng được kết buộc với một dấu tham số, sự kết hợp với biến này vẫn còn có hiệu lực cho đến khi nó được ghi đè hoặc cho đến khi thẻ điều khiển câu lệnh tương ứng được giải phóng Mặc dù kết buộc có thể diễn ra bất kỳ thời điểm nào sau khi một câu lệnh SQL được chuẩn bị, dữ liệu không thực sự được lấy ra từ một biến đã kết buộc cho đến khi câu lệnh SQL được thi hành
Liệt kê 1 minh họa một biến ứng dụng sẽ được kết buộc vào một dấu tham số được mã hóa trong một câu lệnh đơn giản SQL SELECT trong một ứng dụng CLI/ODBC viết bằng ngôn ngữ lập trình C như thế nào Nó cũng minh họa cách thức mà trong đó một giá trị sẽ được cung cấp cho tham số đã kết buộc trước khi câu lệnh được thi hành
Liệt kê 1 Kết buộc các dấu tham số
Trang 25strcat((char *) SQLStmt, "employee WHERE JOB = ?");
// Prepare The SQL Statement
RetCode = SQLPrepare(StmtHandle, SQLStmt, SQL_NTS);
// Bind The Parameter Marker Used In The SQL Statement To
// An Application Variable
RetCode =
SQLBindParameter(StmtHandle, 1,
SQL_PARAM_INPUT,
Trang 26strcpy((char *) JobType, "DESIGNER");
// Execute The SQL Statement
Trang 27nào khác, không phải câu lệnh SELECT hay câu lệnh VALUES, thì việc xử lý bổ sung thêm duy nhất sau khi thi hành là kiểm tra mã trả về của hàm CLI/ODBC để bảo đảm rằng câu lệnh được thi hành như mong đợi Tuy nhiên, nếu một truy vấn
đã được thi hành, đặc biệt là một truy vấn có trả về nhiều hàng, các bước bổ sung thêm có thể cần thiết để lấy ra dữ liệu từ bộ dữ liệu kết quả được tạo ra
Khi nhiều hàng được trả về để đáp lại một truy vấn, chúng được lưu trữ trong các vùng lưu trữ dữ liệu, được tham chiếu bởi các thẻ điều khiển kết nối và thẻ điều khiển câu lệnh kết hợp với câu lệnh SQL đã thi hành Kết quả là, có thể cần đến các bước bổ sung sau đây để lấy ra từng hàng dữ liệu từ bộ dữ liệu kết quả đã tạo ra:
1 Xác định cấu trúc (có nghĩa là, số lượng các cột, các kiểu dữ liệu cột và các chiều dài dữ liệu) của bộ dữ liệu kết quả được tạo ra Thực hiện điều này bằng cách thi hành các hàm SQLNumResultCols() ,SQLDescribeCol() và
SQLColAttributes()
2 Kết buộc các biến ứng dụng với các cột trong bộ dữ liệu kết quả, sử dụng hàm SQLBindCol() (tùy chọn)
3 Lặp lại nhiều lần việc tìm nạp hàng dữ liệu tiếp theo từ bộ dữ liệu kết quả
đã tạo ra và sao chép nội dung của nó tới các biến ứng dụng bị ràng buộc Việc này thường được thực hiện bằng cách liên tục gọi hàm SQLFetch() trong một vòng lặp (Các giá trị cho các cột không kết buộc tới các biến ứng dụng trong Bước 2 có thể được lấy ra bằng cách gọi hàm SQLGetData() sau khi một hàng mới
đã được tìm nạp)
Trong bước đầu tiên, câu lệnh SQL đã chuẩn bị hay đã thi hành sẽ được phân tích
để xác định cấu trúc của bộ dữ liệu kết quả được tạo ra Nếu câu lệnh SQL đã được viết mã lệnh cứng vào ứng dụng, bước này sẽ không cần thiết vì cấu trúc của
bộ dữ liệu kết quả được tạo ra đã được biết Tuy nhiên, nếu câu lệnh SQL được
Trang 28sinh ra trong thời gian chạy ứng dụng, thì phải truy vấn bộ dữ liệu kết quả được tạo ra để có được thông tin này
Một khi cấu trúc của bộ dữ liệu kết quả đã được biết, một hoặc nhiều biến ứng dụng có thể bị ràng buộc vào các cột cụ thể trong bộ dữ liệu kết quả (giống như các biến ứng dụng bị ràng buộc với dấu tham số của câu lệnh SQL) Trong trường hợp này, các biến ứng dụng được sử dụng như là các đối số đầu ra, chứ không phải
là các đối số đầu vào và dữ liệu được lấy ra và được ghi trực tiếp vào chúng bất cứ khi nào hàm SQLFetch() được gọi Tuy nhiên, bởi vì hàm SQLGetData() cũng có thể được sử dụng để lấy ra dữ liệu từ một bộ dữ liệu kết quả, nên kết buộc biến/cột của ứng dụng là tùy chọn
Trong bước thứ ba, dữ liệu được lưu trữ trong bộ dữ liệu kết quả được lấy ra bằng cách gọi hàm SQLFetch() lặp lại nhiều lần (thường trong một vòng lặp) cho đến khi dữ liệu không còn nữa Nếu các biến ứng dụng đã được kết buộc với các cột trong bộ dữ liệu kết quả, các giá trị của chúng sẽ được tự động cập nhật mỗi khi hàm SQLFetch() được gọi Mặt khác, nếu các kết buộc cột đã không được thực hiện, hàm SQLGetData() có thể được sử dụng để sao chép dữ liệu từ một cột cụ thể tới một biến ứng dụng thích hợp Hàm SQLGetData() cũng có thể được dùng
để lấy ra các giá trị dữ liệu cột có chiều dài biến đổi lớn theo nhiều đoạn nhỏ (điều này không thể được thực hiện khi sử dụng kết buộc các biến ứng dụng) Tất cả các
dữ liệu được lưu trữ trong một bộ dữ liệu kết quả có thể được lấy ra khi sử dụng bất kỳ sự kết hợp nào của hai phương pháp này
Liệt kê 2 minh họa một biến ứng dụng sẽ bị ràng buộc vào các cột trong một bộ dữ liệu kết quả trong một ứng dụng CLI/ODBC được viết bằng ngôn ngữ lập trình C như thế nào Nó cũng minh họa cách thức trong đó các dữ liệu trong một bộ dữ liệu kết quả thường được lấy ra bằng cách gọi hàm SQLFetch() lặp lại nhiều lần
Trang 29Liệt kê 2 Kết buộc các cột
LastName, sizeof(LastName), NULL);
// While There Are Records In The Result Data Set
// Produced, Retrieve And Display Them
while (RetCode != SQL_NO_DATA)
Trang 30dữ liệu; hoặc là các ảnh hưởng của tất cả các hoạt động được thực hiện trong một giao dịch được áp dụng cho cơ sở dữ liệu và trở thành thường trực (được cam kết
Trang 31), hoặc các ảnh hưởng của tất cả các hoạt động đã thực hiện được rút lại (khôi phục lại) và cơ sở dữ liệu được trả về tới trạng thái mà nó đã có trước khi giao dịch được bắt đầu
Từ quan điểm xử lý giao dịch, một ứng dụng CLI/ODBC có thể được cấu hình sao cho nó chạy ở một trong hai chế độ: cam kết tự động hoặc cam kết thủ công Khi chế độ cam kết tự động được sử dụng, mỗi câu lệnh SQL riêng biệt được xử lý như là một giao dịch đầy đủ và mỗi giao dịch được tự động cam kết sau khi câu lệnh SQL thực hiện thành công Đối với bất cứ các câu lệnh nào không phải là câu lệnh SELECT, hoạt động cam kết này diễn ra ngay lập tức sau khi câu lệnh được thi hành Đối với câu lệnh SELECT, hoạt động cam kết diễn ra ngay lập tức sau khi con trỏ được sử dụng để xử lý bộ dữ liệu kết quả được đóng lại (Hãy nhớ rằng CLI/ODBC tự động khai báo và mở một con trỏ nếu cần thiết) Chế độ cam kết tự động là chế độ cam kết mặc định và thường là đủ cho các ứng dụng CLI/ODBC đơn giản Tuy nhiên, các ứng dụng lớn hơn, đặc biệt là những ứng dụng có thực hiện các hoạt động cập nhật, nên chuyển sang chế độ cam kết thủ công ngay sau khi một kết nối nguồn dữ liệu được thiết lập Lời gọi hàm sử dụng để chuyển sang chế độ cam kết thủ công tương tự như thế này:
Trang 32thúc tường minh khi hàm SQLEndTran() được gọi Hàm CLI/ODBC này được sử dụng để cuộn ngược lại giao dịch hoặc cam kết tất cả các thay đổi mà giao dịch hiện tại thực hiện Như vậy, tất cả các hoạt động được thực hiện đối với một
nguồn dữ liệu trong khoảng thời gian giữa thời điểm lần đầu tiên truy cập nó và thời điểm gọi hàm SQLEndTran() sẽ được coi như là một giao dịch
Giải phóng các thẻ điều khiển câu lệnh
Khi các kết quả của một câu lệnh SQL đã được xử lý và vùng lưu trữ dữ liệu của câu lệnh SQL đã được phân bổ khi việc xử lý giao dịch được bắt đầu không còn cần thiết nữa, bộ nhớ dành để lưu trữ các dữ liệu này phải được giải phóng Để giải phóng vùng lưu trữ dữ liệu kết hợp với một thẻ điều khiển câu lệnh cụ thể, hãy gọi hàm SQLFreeHandle() với tùy chọn SQL_HANDLE_STMT và chỉ rõ thẻ điều khiển câu lệnh thích hợp (ví dụ, SQLFreeHandle(SQL_HANDLE_STMT, StmtHandle)) Khi được gọi ra, hàm CLI/ODBC này thực hiện các nhiệm vụ sau:
Bỏ kết buộc tất cả các biến ứng dụng trước đây ràng buộc với tham số
Bỏ kết buộc tất cả các biến ứng dụng trước đây ràng buộc với cột
Đóng bất kỳ con trỏ nào đang mở và loại bỏ kết quả của chúng
Hủy bỏ thẻ điều khiển đã chỉ rõ và giải phóng tất cả các tài nguyên kết hợp với nó
Nếu một thẻ điều khiển câu lệnh không được giải phóng, nó có thể được sử dụng
để xử lý các câu lệnh SQL khác
Trang 33
Chấm dứt các kết nối nguồn dữ liệu
Ngay trước khi một ứng dụng CLI/ODBC kết thúc và điều khiển được trả về cho
hệ điều hành, hãy chấm dứt tất cả các kết nối nguồn dữ liệu đã được thiết lập và giải phóng tất cả các tài nguyên đã được cấp phát trong thời gian khởi tạo (Thông thường, các tài nguyên này bao gồm một vùng lưu trữ dữ liệu môi trường và một hoặc nhiều vùng lưu trữ dữ liệu kết nối)
Chấm dứt kết nối cơ sở dữ liệu hiện có bằng cách gọi hàm SQLDisconnect() với thẻ điều khiển kết nối thích hợp đã chỉ rõ Để giải phóng các vùng lưu trữ dữ liệu kết nối tương ứng, hãy gọi hàm SQLFreeHandle() với tùy chọn
SQL_HANDLE_DBC và thẻ điều khiển kết nối thích hợp đã chỉ rõ Sau khi tất cả các vùng lưu trữ dữ liệu kết nối được cấp phát trước đây đã được giải phóng, vùng lưu trữ dữ liệu môi trường mà các vùng lưu trữ dữ liệu kết nối kết hợp với nó cũng được giải phóng bằng cách gọi hàm SQLFreeHandle(), lúc này với tùy chọn
SQL_HANDLE_ENV và thẻ điều khiển môi trường thích hợp được chỉ rõ
Ghép tất cả cùng với nhau
Bạn đã thấy một số thành phần cơ bản được sử dụng để xây dựng các ứng dụng CLI/ODBC Bây giờ bạn sẽ thấy tất cả chúng phối hợp với nhau để tạo ra một ứng dụng CLI/ODBC có tương tác với một cơ sở dữ liệu DB2 như thế nào Một ứng dụng CLI/ODBC đơn giản, được viết bằng ngôn ngữ lập trình C, nhận và in ra các
Trang 34mã số nhận dạng nhân viên và các tên họ cho tất cả các nhân viên có chức danh công việc là DESIGNER, sẽ trông giống như sau:
Liệt kê 3 Một ứng dụng CLI/ODBC đơn giản