Xay dung giao dien lap trinh OCI
Trang 1PHẦN I : CÁC KHÁI NIỆM CƠ BẢN
CHƯƠNG I : GIỚI THIỆU OCI VÀ NHỮNG ĐẶC TÍNH CỦA NÓI-Oracle Call Inteface(OCI)
SQL là ngôn ngữ lập trình không có cấu trúc Chương trình viết trong nó dùng tập dữ liệu để hoạt động nhưng sẽ không xác định những hoạt động gì được thực thi , hoặc những hoạt động đó thực thi như thế nào SQL dễ học và dễ dùng để giải quyết CSDL Nó cụng là một ngôn ngữ chuẩn dùng để truy cập và thao dữ liệu trong các quan hệ hiện đại và quan hệ hướng đối tượng trong các hệ thống CSDL
Tuy nhiên hầu hết các ngôn ngữ có cấu trúc như C , C++ thì việc thực thi của hầu hết các câu lệnh phụ thuộc vào những câu lệnh trước đó hoặc những câu lệnh lồng bên trong nó và những câu lệnh điều khiển như lặp , rẽ nhánh mà không có trong SQL Những ngôn ngữ có cấu trúc phức tạp hơn SQL nhưng chúng mềm dẻo và mạnh hơn SQL
OCI cho phép phát triển những ứng dụng mà trong đó có sự liên kết khả năng truy cập dữ liệu của SQL và C OCI hổ trợ tất cảcác định nghĩa dữ liệu SQL , thao tác dữ liệu , truy vấn , các điều khiển thuận lợi mà đã có sẳn trong Oracle8 Server
PL/SQL cũng có nhiều thuận lợi vì nó là mở rộng từ Oracle theo thủ tục đến SQL Theo đó các ứng dụng có thể phát triển mềm dẻo và mạnh hơn các ứng dụng chỉ viết bằng SQL Vì vậy OCI cung cấp các thuận lợi trong việc truy cập và thao tác các đối tượng trong Oracle 8 Server
OCI là một phần mềm giao tiếp cho phép thao tác dữ liệu và sơ đồ CSDL Oracle Hình 1-1 cho thấy việc dịch và liên kết một chương trình OCI tương tự như việc dịch và liên kết một ứng dụng không phải là CSDL Không cần bước xử lý trước hoặc dịch trước
Hình 1-1 : Quá trình phát triển OCI
Chú ý : Trong một số phần cứng chuẩn cần một số thư viện khác thêm vào thư viện OCI để liên kết các chương trình OCI đúng đắn hơn Cần kiểm tra tài liệu về hệ thống Oracle của bạn để biết cần phải thêm những thư viện nào cần thêm vào.
II- Các phát biểu SQL
Trang 2Một trong những việc chính của SQL là xử lý các phát biểu Các phát biểu khác nhau cần những bước xử lý khác nhau Điều này rất quan trọng trong việc mã hoá ứng dụng OCI Oracle8 thừa nhận 8 loại phát biểu sau :
ª Ngôn ngữ định nghĩa dữ liệu (DDL) ª Các phát biểu điều khiển
ª Điều khiển thực thi ª Điều khiển hệ điều hành ª Điều khiển hệ thống
ª Ngôn ngữ thao tác dữ liệu (DML) ª Truy vấn
Ghi chú: các truy vấn được phân loại như các phát biểu DML nhưng các ứng dụng OCI xử lý truy vấn khác nhau Vì vậy chúng phải được suy nghĩ một cách riêng biệt
ª PL/SQL ª SQL nhúng
1 Ngôn ngữ định nghĩa dữ liệu
Các phát biểu DDL quản lý sơ dồ các đối tượng trong CSDL Các phát biểu DDL tạo ra các bảng mới , xoá các bảng cũ , thiết lập sơ đồ các đốitượng khác Vì vậy chúng diều khiển truy cập đến một sơ đồ các đối tượng Ví dụ :
CREATE TABLE employees
GRANT UPDATE , INSERT ,DELETE ON employees TO joe
Các phát biểu DDL cũng cho phép bạn làm việc với các object trong Oracle8 Server các phát biểu sau sẽ tạo ra một bảng các object
CREATE TYPE person_t AS OBJECT( name VARCHAR2(30),
ssn VARCHAR2(12), address VARCHAR2(50)) CREATE TABLE person_tab OF person_t
2 Các phát biểu điều khiển
Các ứng dụng OCI giải quyết các điều khiển thực thi , điều khiển hệ điều hành , diều khiển hệ thống tương tự như các phát biểu DML
3 Ngôn ngữ thao tác dữ liệu
Các phát biểu DML có thể thay dữ liệu trong các bảng CSDL Chẳng hạn các phát biểu DML dung để :
Thêm các hàng vào một bảng
Cập nhật các giá trị của các cột tồn tại trong các hàng
Trang 3 Xoá các hàng trong một bảng Khoá một bảng trong CSDL
Giải quyết quá trình thực thi cho một phát biểu SQL
Các phát biểu DML có thể yêu cầu một ứng dụng cung cấp dữ liệu cho CSDL , là đầu vào được đóng gói (binding)
Binding
Hầu hiết các phát biểu DML và một số truy vấn yêu cầu một chương trình đưa dữ liệu vào Oracle như là một phần của các phát biểu SQL hoặc PL/SQL Khi chương trình được dịch cần phải biết dữ liệu là hằng hay dạng chữ Ví dụ phát biểu SQL sau sẽ thêm một employee vào CSDL
Một phát biểu cứng nhắc như vậy sẽ có một vài hạn chế Bạn phải thay đổi phát biểu và dịch lại chương trình mỗi khi thêm employee mới vào CSDL Để chương trình mềm dẻo hơn bạn có thể viết chương trình để user nhập dữ liệu mỗi khi chương trình chạy
Khi chuẩn bị cho một phát biểu SQL hoặc khối PL/SQL mà dữ liệu được cung cấp vào lúc chạy Ví dụ , phát biểu SQL có 5 nơi giữ dữ liệu đại diện cho 5 đầu vào dữ liệu (bắt đầu bằng ":")
INSERT INTO emp VALUES
Bạn có thể dùng nơi giữ dữ liệu đại diện cho các biến đầu vào trong các phát biểu DELETE , INSERT , SELECT , UPDATE hoặc khối PL/SQL ở bất kỳ vị trí nào của phát biểu , chúng có thể là biểu thức hoặc giá trị dạng chữ Đối với khối PL/SQL các nơi giữ dữ liệu có thể đại diện cho các biến đầu ra Tên của chúng không được dùng để đặt tên cho các đối tượng khác của Oracle như table hoặc column
đối với mỗi nơi giữ dữ liệu trong phát biểu SQL hoặc khối PL/SQL bạn phải gọi một thủ tục OCI mà nhận địa chỉ của biến chỉ đến nơi chứa dữ liệu Khi phát biểu thực thi , Oracle nhận dữ liệu mà chương trình đặt trong input , bind , biến và gởi nó đến server cùng với phát biểu SQL đó
4 Các truy vấn
Truy vấn là phát biểu nhận dữ liệu từ một CSDL Một truy vấn có thể trả về không , một , hoặc nhiều hàng dữ liệu Tất cả các truy vấn bắt đầu bằng từ khóa SELECT
Các truy vấn truy cập dữ liệu trong các bảng và chúng được phân loại cùng với các phát biểu DML Tuy nhiên các ứng dụng OCI xử lý các truy vấn khác nhau , do vậy chúng phải được xác định riêng biệt
Các truy vấn yêu câàu chương trình cung cấp dữ liệu đến CSDL sử dụng các biến đầu vào (bind) như ví dụ sau :
SELECT name
WHERE empno= :empnumber
Trong phát biểu SQL trên , :empnumber là một nơi giữ dữ liệu đại diện cho một giá trị sẽ được cung cấp bởi ứng dụng đó
Khi xử lý một truy vấn , một ứng dụng OCI cần định nghĩa các biến output để nhận các giá trị trả về Trong phát biểu trên cần định nghĩa một biến output để nhận giá trị name trả về
Trang 4Các phát biểu sẽ trả dữ liệu liệu về từ CSDL đến ứng dụng của bạn Khi xử lý một truy vấn bạn phải định nghĩa một biến output hoặc một mảng các biến output cho mỗi phát biểu SELECT mà bạn muốn nhận dữ liệu từ nó Bước định nghĩa sẽ tạo ra sự kết hợp để xác định nơi chứa kết quả trả về và theo định dạng gì
Bạn cần phải định nghĩa hai output , một để nhận giá trị trả về từ cột name , một để nhậngiá trị trả về từ cột ssn
5 PL/SQL
PL/SQL là các mở rộng theo hướng thủ tục của SQL PL/SQL xử lý các công việc phức tạp hơn các truy vấn và các phát biểu SQL PL/SQL cho phép nhóm một số phát biểu thành một khối đơn và thực thi như một đơn vị Đó là :
Một hoặc nhiều phát biểu SQL Các khai báo biến
Các phát biểu phân công
Các phát biểu điều khiển thủ tục như : IF…THEN…ELSE , LẶP Ngoại trừ handing
Có thể dùng khối PL/SQL trong chương trình để : Gọi các thủ tục và hàm
Dịch các phát biểu điều khiển thủ tục cùng với các phát biểu SQL để thực thi như một đơn vị
Truy cập các thuộc tính PL/SQL đặc biệt như record , table , con trỏ các vòng lặp , ngoại trừ handing
Sử dụng các biến con trỏ
Truy cập và thao tác các đối tượng trong một Oracle8 server
Ví dụ PL/SQL sau cho thấy một phát biểu SQL để nhận những giá trị từ một bảng employees Ví dụ này giải thích cách sử dụng nơi giữ dữ liệu trong các phát biểu PL/SQL
Với ý nghĩa đó các nơi giữ dữ liệu không phải là các biến PL/SQL mà chúng chỉ tượng trưng cho các biến đầu vào khi phát biểu được xử lý Chúng cần để giao tiếp với các biến của C trong chương trình của bạn
6 SQL nhúng
OCI xử lý các phát biểu như là các câu của văn bản mà một ứng dụng truyền đến Oracle thực thi Các trình biên dịch trước của Oracle (Pro*C/C++ , Pro*COBOL , Pro* FORTRAN) cho phép lập trình viên nhúng các phát biểu SQL trực tiếp vào mã chương trình ứng dụng của họ Bước dịch trước là cần thiết để tạo ra một ứng dụng có thể thực thi
Trang 5III Các từ đặc biệt của OCI
Các từ đặc biệt để chỉ các phần khác nhau của một phát biểu SQL Ví dụ một phát biểu SQL
bao gồm các phần sau : + Một lệnh SQL : SELECT
+ Hai select-list item : customer và address
+ Một tên của bảng trong mệnh đề FROM : customers
+ Hai cột trong mệnh đề WHERE : bus_type và sales_volume
+ Một giá trị đầu vào dạng chữ trong mệnh đề WHERE : 'SOFTWARE'
+ Một nơi giữ dữ liệu tượng trưng cho một biến đầu vào trong phần thứ hai của mệnh đề WHERE : :sales
Khi phát triển một ứng dụng OCI bạn gọi địa chỉ của các biến vào/ra trong chương trình Đa
chỉ của nơi giữ dữ liệu đại diện cho dữ liệu vào gọi là bind operation Địa chỉ của các biếnđể nhận select-list items gọi là define operation Đối với PL/SQL đều được gọi làoperation
IV Đối tượng hổ trợ trong OCI
Oracle server có những thuận lợi để làm việc với kiểu đối tượng và các đối tượng Một
object type là một cấu trúc dữ liệu mô tả một phần tử của thế giới thực do user định nhĩa Ví
dụ , một CSDL có thể chứa một định nghĩa của đối tượng mà đối tượng đó bao gồm các thuộc tính first-name , last-name , age mô tả những đặc trưng về định danh của con người trong thế giới thực
Định nghĩa object type là cớ sở cho việc tạo các oject mà mô tả các thực thể của object type Sử dụng object type như là định nghĩa cấu trúc , một đối tượng người được tạo ra với các thuộc tính 'Jonh' , Bonivento' , '30' Các object type có thể chứa các method
OCI của Oracle8 bao gồm các hàm mà có nhiều khả năng điều khiển các oject trong Oracle server Đặc biệt là các khả năng sau được thêm vào OCI :
+ Hổ trợ việc thực thi các phát biểu SQL thao tác dữ liệu và thông tin sơ đồ
+ Hổ trợ việc tham chiếu đến các đối tượng và thực thể như các biến đầu vào của phát biểu SQL
+ Hổ trợ việc tham chiếu đến các đối tượng và thực thể như các biến đầu ra cho các phát biểu SQL
+ Hổ trợ việc tham chiếu đến các đối tượng và thực thể từ một CSDL
+ Hổ trợ việc mô tả những thuộc tính của một phát biểu SQL mà nó trả về là các thực thể và các tham chiếu
+ Hổ trợ việc mô tả các thủ tục hoặc hàm của PL/SQL mà có các tham số hoặc kết là đối tượng
Thêm vào đó OCI hổ trợ cho việc thao tác trên các object sau khi chúng được truy cập bởi các phát biểu SQL
V Các loại hàm của OCI
OCI bao gồm 4 tập hàm chính :
Trang 61 OCI relational function : quản lý truy cập dữ liệu và xử lý các phát biểu SQL
2 OCI navigational function : thao tác các đối tượng nhận được từ một Oracle8 server
3 OCI datatype mapping and munipulation function : thao tác trên các thuộc tính dữ liệu của các kiểu Oracle8
4 OCI external procedure function : dùng để viết C gọi từ PL/SQL
VI Những đặc tính mới của Release 8.0
R 8.0 có những đặc tính mới và những thuận lợi cho việc thực hiện : Tăêng các chu trình client-side và giảm các yêu cầu server-side Phát biểu SELECT trả về tập các hàng
API truy cập đến các đối tượng và dữ liệu có liên quan Giảm số chuyến đi vòng tròn trên mạng
Có khả năng điều khiển các cột LOB
Một tập API gọi thực hiện các thao tác trên LOB và trên FILE Cải tiến các khả năng của NLS (National Language Support)
Có sự duy chuyển đường dẫn trong OCI và có một số khả năng trộn lẫn việc gọi cũ và mới trong một ứng dụng
Cải tiến hổ trợ cho nhiều môi trường
Các chức năng thêm vào cung cấp việc truy cập qua lại các object trong một Oracle8 server
VII.Tại sao phải sử dụng OCI ?
Nói chung có nhiều phương pháp truy cập vào một Oracle database như sử dụng ODBC , SQL *Plus … Nhưng OCI giúp truy cập trực tiếp vào Oracle database tiết kiệm được thời gian truy cập Vấn đề thời gian truy cập càng trở nên có ý nghĩa đối với một database lớn
Tuy nhiên các hàm OCI rất phức tạp(có nhiều thông số ) trở không thân thiện đối với người dùng Muốn sử dụng được OCI đòi hỏi người dùng phải am hiểu khá tỉ mỉ về nó Vì thế mục đích của đề tài này là xây dựng một giao diện lập trình thân thiện hơn mà người dùng chỉ cần thao tác một số bước cơ bản thì có thể thực hiện truy cập nhanh chóng và dễ dàng
VIII Một số khái niệm
1 Database server : là khóa để giải quyết vấn đề quản lý thông tin , quản số lượng lớn dữ
liệu và cho phép nhiều user truy cập đồng thời cùng một dữ liệu
Một Oracle server bao gồm : một Oracle server instance và một Oracle database
2 Oracle instance : là sự liên kết giữa các background process và vùng nhớ toàn cục
(System Global area) vùng nhớ dùng chung cho các dữ liệu của user Một Oracle instance có hai loại process :
user process : thực thi mã của chương trình ứng dụng
oracle process : thực thi các công việc của user process và background process nhằm quản lý công việc của oracle server
3 Oracle database : là một hợp các dữ liệu được xem như một đơn vị , chứa và nhận các
thông tin có liên quan với nhau Một oracle database có thể mở(acessable) hoặc đóng(unacessable)
4 Cấu trúc của Oracle database : bao gồm
Logical structure
Trang 7 Physical structure : có 3 loại file + data file : chứa dữ liệu
+ redo log file : ghi nhận các thay đổi data nhằm ngăn chặn các lỗi + control file : dùng để nhận diện database và redo log file
5 Cursor(hay handle) : oracle dùng các vùng dành riêng (private SQL areas) để thi hành
các câu lệnh SQL và lưu trữ thông tin của quá trình Một cursor là một cấu trúc PL/SQL cho phép định danh các vùng này và truy cập thông tin trong nó
6 Oracle process : là các process mà sẽ được gọi bởi các process khác để thực hiện công
việc theo yêu cầu của các process khác này Có 2 loại :
Server process : nhận các yêu cầu của các user process được nối kết đến Nó giao tiếp với các user process và tác động vào Oracle để mang về các kết quả theo yêu cầu cho user
Background process : Oracle tạo một tập các background process cho mỗi instance Nhằm đồng bộ việc thực hiện I/O và giám sát các Oracle process từ đó làm tăng tính xử lý song song để thực thi công việc tốt hơn
7 Program interface :là cơ cấu mà một user process giao tiếp một server process
8 Transaction : là một đơn vị công việc luận lý bao gồm nhiều SQL statement Một
transaction bắt đầu với SQL statement có thể thực thi đầu tiên và kết thúc khi nó được commit hoặc rallback
Một transaction kết thúc khi xảy ra một trong số các điều sau : Sử dụng commit statement hoặc rallback statement
Thực thi DDL statement Nếu transaction hiện tại chứa bất kỳ DML(such as CREATE, DROP, RENAME, ALTER) statement nào thì đầu tiên Oracle sẽ commit transaction hiện tại rồi thực thi và commit DDL như một transaction mới
Disconnect từ Oracle
Một user process kết thúc không bình thường
Sau khi kết thúc một transaction SQL statement có thể thực thi tự động bắt đầu transaction tiếp theo
tầm quan trọng của transaction : Oracle duy trì tính nhất quán dữ liệu dựa vào các transaction Các transaction cho phép ta điều khiển linh hoạt khi làm việc với dữ liệu và bảo vệ sự toàn vẹn dữ liệu ngay cả trong trường hợp gặp sự cố hệ thống
Commit transaction : nghĩa là tạo những thay đổi thường xuyên bới các SQL statement trong
transaction đó
Trước khi một transaction sữa chữa dữ liệu được commit thì xảy ra các d-iều sau :
Oracle tạo ra các rollback segment record trong vùng đệm rollback segment của SGA(system global area) để chứa các giá trị dữ liệu cũ đã bị thay đổi bởi các SQL statement của transaction
Oracle đã tạo ra các redo leg trong redo log buffer của SGA Những thay đổi này có thể được ghi vào đĩa trước khi commit transaction
Các thay đổi được đưa đến database buffer và chúng có thể đi đến đĩa trước khi một transaction thực sự được commit
Khi một transaction được commit xảy ra các điều sau :
Trang 8 Bảng transaction bên trong nối kết với các bảng ghi phân đoạn rollback(rollback segment records) mà transaction đã được commit để ghi vào bảng unique system change number(SCN) của transaction đó
Process log writer ghi các redo log và SCN vào redo log file Đây sự kiện cơ bản để thiết lập commit transaction
Oracle mở khóa trên các row và table Oracle đánh dấu transaction là "complete"
Rollback transaction : không tạo bất kỳ thay đổi dữ liệu nào mà đã được thực hiện bởi SQL
statement trong một uncommit transaction Oracle cho phép rollback toàn bộ một uncommit transaction hoặc từ một savepoint
IX Giới thiệu Net8
Net8 là lớp phần mềm được sử dụng để giao tiếp giữa client và server hoặc giữa các server Các user process và server process trên các máy khác nhau giao tiếp với nhau thông qua Net8
Net8 là một cơ cấu các protocol thực hiện việc phân bố xử lý và phân bố database Các protocol định nghĩa cách truyền và nhận data trên một mạng
Trong đề tài này việc truy cập oracle database cũng nhờ Net8 để truyền và nhận dữ liệu Hình dưới là kiến trúc của Net8 và chương trình ứng dụng sử dụng thư viện OCI để truy cập vào Oracle database
Trang 9CHƯƠNG II : CÁC BƯỚC CƠ BẢN LẬP TRÌNH OCI I Cấu trúc chương trình OCI
Nói chung mục tiêu của một ứng dụng OCI là nối kết đến Oracle Server , chọn trước một số loại trao đổi data thực hiện việc xử lý data Mỗi ứng dụng OCI được thực hiện theo trình tự các bước như hình 2-1:
Hình 2-1 : Lưu đồ chương trình OCI cơ bản
Trên đây là các bước của một chương trình OCI tổng quát Tuy nhiên tùy thuộc vào chức năng của chương trình (quản lý nhiều giao tiếp , sử dụng object ,…) thì có thể cần thêm một số bước
Quá trình OCI chỉ được khởi tạo một lần , một ứng dụng có thể tạo nhiều môi trường như được minh họa ở hình 2-2 :
Initialize Process
Trang 10II Các cấu trúc của data OCI
Handle và Descriptor là hai cấu trúc không trong suốt được định nghĩa trong các ứng dụng OCI và có thể được chỉ định trực tiếp thông qua các cách gọi được chỉ định rõ ràng , hoặc chỉ định ẩn bởi các hảm OCI
Handle và Descriptor chứa thông tin liên quan đến data , các nối kết hoặc cách thực hiện của ứng dụng
III Handle
Hầu hết Oracle8 OCI gọi danh sách tham số của chúng hoặc nhiều handle một handle là một pointer không trong suốt trỏ đến một vùng lưu trữ được chỉ định bởi thư viện OCI Một handle có thể được sử dụng để chứa phạm vi hoặc thông tin nối kết , hoặc có thể chứa thông
Free Handles &
Data StructuresData StructuresFree Handles &
Trang 11tin về các hàm OCI hoặc data Handle có thể lập trình ứng dụng dễ hơn , bởi vì có thư viện để quản lý data này
Hầu hết các ứng OCI cần truy cập thông tin được lưu trữ trong handle để truy cập thông tin
này ta dùnh hai hàm OCI OCIAttrGet() và OCIAttrSet()
Bảng dưới đây đưa ra danh sách các handle được định nghĩa cho OCI Mỗi kiểu handle , kiểu data C và kiểu handle hằng số được đưa ra
Table 2-1 OCI Handle Types
1 Chỉ định và hủy bỏ handle
Ứng dụng của bạn chỉ định các handle (trừ bind và define handle) thừa nhận môi trường handle riêng biệt Thông qua enviroment handle như một tham số handle chỉ định việc gọi Việc chỉ định handle là rõ ràng
Bind và define handle được chỉ thị với sự thừa nhận một phát biểu handle và chứa thông tin về phát biểu được mô tả bởi các handle đó
Bind và define handle hoàn toàn được chỉ định bởi thư việc OCI
Trang 12Tất cả các handle do user chỉ định trừ enviroment handle phải được chỉ định bởi việc gọi hàm
OCIHandle() Enviroment handle được chỉ định và khởi tạo bằng việc gọi hàmOCIEnvInit() mà nó cần cho mọi ứng dụng OCI.
Một ứng dụng OCI phải giải phóng các handle khi chúng không còn cần thiết thông qua hàm
OCIHanleFree() Khi một handle cha bị giải phóng , tất cả các handle con có liên kết với
cũng bị hủy bỏ và không được sử dụng nữa Ví dụ , khi một phát biểu handle bị giải phóng thì bất kỳ bind và define handle có liên kết với nó cũng bị hủy bỏ
Handle tránh dùng biến toàn cục Handle cũng dự đoán lỗi dễ hơn Error handle được để trả về các lỗi
2 Enviroment handle
Enviroment handle xác định một ngữ cảnh mà các hàm OCI được gọi trong đó Mỗi enviroment handle chứa một vùng cashe cho phép điều khiển vùng nhớ nhanh chóng theo một môi trường thống nhất Khi có nhiều tuyến dùng chung một môi trường thì chúng sẽ khóa truy câp vùng cashe
Enviroment handle được chuyển đến OCIHandleAllocation() như tham số parenth để chỉ
định tất cả các kiểu handle khác , trừ bind và define handle
Trang 13Error handke được truyền như một tham số trong hầu hết việc gọi hàm OCI Error handle quản lý thông tin về các lỗi xảy ra trong một hoạt động của OCI Nếu một lỗi xảy ra khi gọi
hàm , error handle được truyền đến OCIErrorGet() để thu được thông tin thêm về lỗi xảy ra
Chỉ định error handle là bước đầu tiê trong một ứng dụng OCI
4 Service context và associated handle
Một service context handle định nghĩa những thuộc tính mà xác định ngữ cảnh hoạt động của các lời gọi OCI đến server
Bạn phải chỉ định và khởi tạo service context handle thông qua các hàm
OCIHandleAllocation() hoặc OCILogon() trước khi sử dụng nó
Sevice context quản lý 3 handle :
Server handle : nhận dạng nguồn dữ liệu
user session handle : định nghĩa các vai trò , quyền của một user và ngữ cảnh hoạt động mà các hàm được gọi thực thi
transaction handle : định nghĩa giao dịch mà các quá trình hoạt động của SQL đuợc thực hiện Phạm vi giao dịch bao gồm thông tin trạng thái user session , trạng thái định sẳn (fetch state ) và sự đóng gói nhanh (packe instantiation )
Các ứng dụng chỉ điều khiển một user session cho mỗi nối kết CSDL , tại một thơi điểm có
thể gọi OCILogon() để chỉ định service context và associated handle của nó
Trong các ứng dụng yêu cầu quản lý session phức tạp , service context phải được chỉ định rõ ràng , server handle và user session handle phải đặt rõng ràng trong service context thông
qua gọi hàm OCIServerAttach() và OCISessionBegin() riêng Một ứng dụng tốt cần xác định
giao dịch rõ ràng hoặc sự giao dịch tìm ẩn được tạo ra khi ứng dụng thay đổi CSDL
5 Statement handle , Bind handle và define handle
Một statement handle là ngữ cảnh nhận dạng phát biểu SQL hay PL/SQL và các thuộc tính liên kết của nó
Thông tin về biến input đã nói trong phần bind handle Thư viện OCI chỉ định một bind
handle cho mỗi phạm vi chứa bởi hàm OCIBindByName() hoặc OCIBindByPos() User
không cần phải chỉ định bind handle Chúng được chỉ định rõ ràng bằng lời gọi bind (bind call)
Để lưu data trả về bởi một truy vấn được cải tiến và lưu trữ theo sự định rõ của các define handle Thư viện OCi chỉ định một define handle cho mỗi biến output bằng hàm
OCIdefineByPos() User không cần chỉ định define handle Chúng được chỉ định rõ bằng lới
gọi define
6 describe handle
Để sử dụng describe ta gọi hàm OCIDescribeAny() Lời gọi này chứa thông tin về gis3n đồ
các object trong một CSDL (function , procedure) Lời gọi này nhận một describe handle như một tham số của nó, thông tin về object được mô tả trong đó Khi lời gọi hoàn thành describe handle được định vị với thông tin về object Ư&1ng OCI có thể chứa thông tin mô tả thông qua các thuộc tính của tham số mô tả
7 Security handle
8 Complex object retrieval (COR) handle
Được dùng cho một số ứng dụng OCI làm việc với các object trong một Oracle8 server Handle này chứa mô tả COR (COR Descritor ) cung cấp một số lệnh để OCI thu được các object mà được tham chiếu bởi các object khác
Trang 149 Các thuộc tính handle
Tất cả các OCI handle có những thuộc tính rõ ràng Những thuộc tính này htực hiện lưu trữ
data trong handle Dùng hàm OCIAttrGet() để đọc những thuộc tính handle , dùng hàmOCIAttrSet() để set thuộc tính
Ví dụ : các phát biểu sau set username trong transaction handle bằng cách viết thuộc tính OCI_ATTR_USERNAME
text username[] = "scott";
err = OCIAttrSet ((dvoid*) mysessp, OCI_HTYPE_SESSION, (dvoid*) username, (ub4) strlen(username), OCI_ATTR_USERNAME,
(OCIError *) myerrhp);
Tiếp theo việc set các tham số giải thích việc sử dụng OCIAttrGet() để đọc mã hàm của hàm OCI cuối cùng được xử lý trong một handle (trong trường hợp này là bind handle )
ub4 fcode = 0; OCIBind *mybndp;
err = OCIAttrGet( (dvoid*) mybndp, OCI_HTYPE_BIND, (dvoid*) &fcode, (ub4) 0, OCI_ATTR_FNCODE,(OCIError *) myerrhp);
Một số hàm OCI yêu cầu các thuộc tính handle phải được set trước một giá trị trước khi hàm Ví dụ , khi hàm OCISessionBegin() được gọi để thiết lập việc login của user thì username và password được đưa vào user session handle trước khi lời gọi hàm được tạo thành
Những hàm OCI khác hữu dụng để trả về data trong các thuộc tính của handle sau khi hàm hoàn tất chẳng hạn khi gọi hàm OCIStmtExcute() để thực thi một truy vấn SQL thì thông tin mô tả liên quan đến select-list items được trả về trong statement handle
10 Chỉ định vùng nhớ cho user
Kni gọi hàm OCIEnvInit() thì enviroment handle được khởi tạo đồng thời chỉ định handle chung (OCIHandleAlloc())và chỉ định descriptor /locator (OCIDescritorAlloc()) sẽ gọi một tham số xtramem_sz trong danh sách tham số của chúng Tham số này được dùng để định rõ tổng vùng nhớ của user sẽ được chỉ định cho handle đó
Tiêu biểu , mộtứng dụng sử dụng tham số này để chỉ định một cấu trúc định nghĩa ứng dụng mà có thời gian sống như handle
Cấu trúc này được sử dụng cho ứng dụng "bookeeping" hoặc chứa thông tin ngữ cảnh
Sử dụng tham số xtramem_sz có nghĩa là ứng dụng không cần chỉ định rõ và phân phối vùng nhớ cũng như mỗi handle được chỉ định và được phân phối Vùng nhớ này được chỉ định song song với handle cũng như việc giải phóng handle trong các cấu trúc data của user
IV Descriptors and Locators
OCI descriptors và Locator là các cấu trúc data không trong suốt quản lý các thông tin data rõ ràng OCI có 6 loại descriptor và locator được trình bày trong bảng 2-2 cùng với kiểu data của C và kiểu hằng của OCI mà nó chỉ định descriptor trong lời gọi đến hàm OCIDescriptoAlloc() Hàm OCIDescriptorAlloc() giải phóng các descriptor và locator
Table 2-2 Descriptor Types
Trang 15OCILobLocator LOB datatype locator OCI_DTYPE_LOB
OCIComplexObjectComp complex object descriptor OCI_DTYPE_COMPLEXOBJECTCOMP
OCISnapshot : được dùng trong việc thực thi các phát biểu
OCILOBLocator : được sử dụng cho LOB (OCI_DTYPE_LOB) hoặc FILE (OCI_DTYPE_FILE)
OCIParam : được sử dụng cho các lời gọi mô tả
OCIRowid : đuợc sử dụng cho binding hoặc defining các giá trị ROWID OCIComplexObjectComp : được sử dụng cho thu các object phức hợp 1 OCISnapshot descriptor
Là một tham số tùy chọn để thực thi lời gọi hàm OCIStmtExcute() Nó ngụ ý rằng một truy vấn được thực thi tại một thời điểm tương phản với một database snapshot Một database snapshot mô tả trạng thái của một database tại một thời điểm
Có thể chỉ định một snapshot descriptor bằng lời gọi OCIDescriptorAlloc() thông qua tham số kiểu OCI_DTYPE_SNAP
2 LOB Datatype Locator
Một LOB (large object) là một kiểu data của Oracle có thể lê đến 4Gbytes data dạng nhị phân (BLOB) hoặc dạng ký tự (CLOB) Trong một database , một cấu trúc data không trong suốt gọi đến LOB Locator được lưu trong cột LOb của một của database hoặc thuộc tính LOB của một object Locator như một pointer trỏ đến giá trị LOB thực mà được chứa trong một vị trí riêng biệt
OCI LOB Locator được sử dụng để thực hiện các hoạt động của OCI tương ứng với một LOB (BLOB , CLOB) Các hàm OCI không nhận các giá trị LOB thực như các tham số , tất cả các lời gọi hoạt động trên cơ sở LOB locator Descriptor này , OCI Lob Locator cũng được sử dụng trong các hoạt động trên FILE
Chú ý : hai kiều LOB locator không được hoán đổi nhau khi liên kết hoặc định nghĩa một BLOB hặc CLOB , ứng dụng nhận locator hợp lệ khi chỉ định việc sử dụng OCI_DTYPE_LOB Tương tự đối với BFILE , ứng dụng phải chỉ định locator sử dụng OCI_DTYPE_FILE khi liên kết và định nghĩa
Một ứng dụng OCI có thể thu được một locator từ server bằng cách đưa ra một phát biểu SQL chứa cột LOB hoặc thuộc thuộc tính như là một phần tử trong select-list Trong ví dụ này OCI đầu tiên sẽ chỉ định LOB locator sau đó sử dụng nó để định nghĩa một biến output Tương tự , một LOB locator được sử dụng như một phần của một hoạt động liên kết để tạo một sự kết hợp giữa một LOB và một nơi chứa (placeholder)
Trong một phát biểu SQL :Kiểu data locator (OCI Lob Locator) là kiểu data không có hiệu lực khi nối kết với Oracle server
3 Parameter Descriptor
Các ứng dụng OCI sử dụng các parameter descriptor để thu được thông tin về các cột select-list hoặc giản đồ các object Thông tin này được thu thông qua một hoạt động mô tả
Trang 16Parameter descriptor là một kiểu descriptor không chỉ định việc sử dụng OCIDescriptorAlloc() Bạn chỉ có thể thu được nó như một thuộc tính mô tả, phát biểu hoặc liên kết để thu được đối tượng phức hợp thông qua định rõ vị trí của tham số khi gọi OCIParametetGet()
4 ROWID descriptor
ROWID descriptor được sử dụng bởi các ứng dụng mà cần cần phục hồi và sử dụng các Oracle ROWID Kích thước và cấu trúc của ROWID đã bị thay đổi từ Oracle7 sang Oracle8 và nó không trong suốt đối với user Để làm việc với một ROWID sử dụng Oracle8 OCI , một ứng dụng có thể định nghĩa một ROWID descriptor với một vị trí trong select-list của SQL và thu được một ROWID vào descriptor Descriptor này sau đó được ràng buộc đến một biến input trong phát biểu INSERT hoặc mệnh đề WHERE
5 Complex object descriptor
Để sử dụng các object chương trình phải được khởi tạo trong chế độ OCI_OBJECT dùng hàm
OCIInitialize()
6 Chỉ định vùng nhớ cho user
Lời gọi hàm OCIDescriptorAlloc() có tham số xtramem_sz trong select-list Tham số này được dùng để định rõ vùng nhớ cho user được chỉ định cùng với locator hoặc descriptor tiêu biểu , một ứng dụng sử dụng tham số này để chỉ định một cấu trúc ứng dụng được định nghĩa có thời gian sống như descriptor hoặc locator Cấu trúc này được sử dụng cho ứng dụng "bookeeping" hoặc lưu trữ thông tin ngữ cảnh
Sử dụng tham số xtramem_sz có nghĩa là ứng dụng không cần chỉ định rõ ràng và phân phối vùng nhớ cũng như mỗi descriptor hoặc locator phải được chỉ định và phân phối Vùng nhớ này được chỉ định cùng với locator hoặc descriptor cũng như giải phóng descriptor hoặc locator khỏi cấu trúc data của user
Hàm OCIHandleAlloc() có một tham số giống như việc sử dụng vùng nhớ cho user mà có thời gian sống như handle
Hàm OCIEnvInit() có một tham số giống như việc sử dụng vùng nhớ cho user mà có thời gian sống như enviroment handle
V Các bước lập trình OCI
Mỗi bước bạn thực hiện trong một ứng dụng OCI được mô tả chi tiết hơn trong các phần sau Một vài bướclà tùy ý Chẳng hạn bạn không cần phải mô tả hoặc định nghĩa select-list items nếu phát biểu không phải là một truy vấn
Các phần sau mô tả các bước được yêu cầu đối với một ứng dụng Oracle8 OCI : Có 3 bước chính để khởi tạo môi trường OCI :
1 Khởi tạo một quá trình OCI
Quá trình khởi tạo OCIInitialize() phải được gọi trước khi gọi các hàm OCI khác Tham số mode định rõ ứng dụng chạy trong một môi trường liên kết (mode=OCI_THREAD) hoặc sẽ tạo ứng dụng các objedt(mode=OCI_OBJECT) Khởi tạo chế độ object nếu ứng dụng liên kết và định nghĩa các object hoặc ứng dụng sử dụng các object navigation của OCI
Vì vậy chương trình chọn để sử dụng hoặc những thuộc tính này (mode=OCI_DEFAULT) hoặc cả hai chọn lựa độc lập (mode=(OCI_THREAD | OCI_OBJECT))
User định rõ hàm OCIInitialize() để định nghĩa các hàm quản lý bộ nhớ
2 Chỉ định các handle và descriptor
Trang 17Sử dụng hàm OCIHandleAlloc() để chỉ định các handle , trong trường hợp OCI đã chỉ định handle thì không cần dùng hàm này(chẳng hạn dùng hàm OCIDefineByPos() thì OCI chỉ định handle).
Tùy theo chức năng của ứng dụng mà một số handle trong các handle sau được chỉ định : error handle (tùy chọn)
service context handle (bắt buộc) statement handle (bắt buộc) describe handle (tùy chọn) server handle (bắt buộc) user session handle (bắt buộc) transaction handle (tùy chọn)
complex object retrieval handle (tùy chọn)
3.Khởi tạo , nối kết vào tạo session
Sau khi gọi hàm OCIInitialize() phải gọi hàm OCIEnvInit() để khởi tạo environment handle Lúc này có hai tùy chọn
Tùy chọn 1 : Single User, Single Connection
Ứng dụng chỉ quản lý một single user session cho mỗi nối kết database tại một thời điểm với username và password cụ thể
Ví dụ :
OCILogon(envhp, errhp, &svchp, "scott", nameLen, "tiger", passwdLen, "oracle8", dbnameLen)
Kết thúc nối kết bởi hàm OCILogoff()
Trong trường hợp này service context, server và user session handles là chỉ đọc
Tùy chọn 2 :Multiple Sessions hoặc Connections
Sử dụng khi ứng dụng quản lý nhiều user session trên một nối kết database Phải sử dụng các hàm
OCIServerAttach() :để tạo đường truy cập nguồn dữ liệu
OCISessionBegin() : cho phép user có thể làm việc trên server đó
4.Xử lý SQL
5.Commit hoặc Rollback
Để ghi nhận thay đổi đến database dùng hàm OCITransCommit() Ứng dụng có thể tạo transaction tường minh hoặc không tường minh
Để rollback một transaction dùng hàm OCITransRollback() Nếu ứng dụng disconnect từ Oracle mà không phải logout và không gọi hàm OCITransCommit() thì các transaction tích cực được tự động rollback
6.Kết thúc ứng dụng
Phải gọi các hàm sau đây ở bước kết thúc ứng dụng OCI: 1 OCISessionEnd() : để xoá user session cho mỗi session
2 OCIServerDetach() :xoá đường truy cập vào mỗi dữ liệu nguồn 3 OCIHandleFree() :giải phóng các handle
Hoặc
4 Xoá environment handle(các handle liên kết với nó đực giải phóng tự động)
Trang 18ƠNG III : CÁC KIỂU DỮ LIỆU
Giá trị dữ liệu được lưu bên database theo định dạng riêng được gọi là kiểu dữ liệu bên trong (internal datatype) Ví dụ : CHAR , NUMBER , DATE
Chương trình ứng dụng không làm việc với kiểu dữ liệu bên trong mà chỉ làm việc với kiểu dữ liệu của một ngôn ngữ lập trình cụ thể Khi có sự truyền dữ liệu giữa OCI client program và database table thì thư viện OCI sẽ chuyển đổi từ internal datatype sang external datatype External datatype là các kiểu dữ liệu của một ngôn ngữ lập trình , nó được định nghĩa trong các file header
Table 3-1 Internal Oracle Datatypes
Internal Oracle Datatype Maximum Internal Length Datatype Code
User-defined type (object type,
Null-terminated
Trang 19LONG 8 char[n] SQLT_LNG
ROWID
NAMED
Table 3-4 Format of the DATE Datatype
Trang 20typedef int eword; typedef unsigned int uword; typedef signed int sword; #else
#define eword int
#define uword unsigned int #define sword signed int
Trang 21#endif
#define EWORDMAXVAL ((eword) INT_MAX) #define EWORDMINVAL ((eword) 0)
#define UWORDMAXVAL ((uword)UINT_MAX) #define UWORDMINVAL ((uword) 0)
#define SWORDMAXVAL ((sword) INT_MAX) #define SWORDMINVAL ((sword) INT_MIN) #define MINEWORDMAXVAL ((eword) 32767) #define MAXEWORDMINVAL ((eword) 0) #define MINUWORDMAXVAL ((uword) 65535) #define MAXUWORDMINVAL ((uword) 0) #define MINSWORDMAXVAL ((sword) 32767) #define MAXSWORDMINVAL ((sword) -32767)
typedef unsigned char ub1; typedef signed char sb1; #else
#define eb1 char
#define ub1 unsigned char #define sb1 signed char #endif
#define EB1MAXVAL ((eb1)SCHAR_MAX) #define EB1MINVAL ((eb1) 0)
Trang 22#define SB1MAXVAL ((sb1)SCHAR_MAX) #define SB1MINVAL ((sb1)SCHAR_MIN) #define MINEB1MAXVAL ((eb1) 127) #define MAXEB1MINVAL ((eb1) 0) #define MINUB1MAXVAL ((ub1) 255) #define MAXUB1MINVAL ((ub1) 0) #define MINSB1MAXVAL ((sb1) 127) #define MAXSB1MINVAL ((sb1) -127) #define UB1BITS CHAR_BIT
#define UB1MASK ((1 << ((uword)CHAR_BIT)) - 1) typedef unsigned char OraText;
#ifndef LUSEMFC # define text OraText #endif
#ifndef lint
typedef short eb2; typedef unsigned short ub2; typedef signed short sb2; #else
#define eb2 short
#define ub2 unsigned short #define sb2 signed short #endif
#define EB2MAXVAL ((eb2) SHRT_MAX) #define EB2MINVAL ((eb2) 0)
#define UB2MAXVAL ((ub2)USHRT_MAX) #define UB2MINVAL ((ub2) 0)
#define SB2MAXVAL ((sb2) SHRT_MAX) #define SB2MINVAL ((sb2) SHRT_MIN) #define MINEB2MAXVAL ((eb2) 32767) #define MAXEB2MINVAL ((eb2) 0) #define MINUB2MAXVAL ((ub2) 65535) #define MAXUB2MINVAL ((ub2) 0) #define MINSB2MAXVAL ((sb2) 32767) #define MAXSB2MINVAL ((sb2)-32767) #if defined(A_OSF)
Trang 23#ifndef lint
typedef int eb4; typedef unsigned int ub4; typedef signed int sb4; #else
#define eb4 int
#define ub4 unsigned int #define sb4 signed int #endif
#define EB4MAXVAL ((eb4) INT_MAX) #define EB4MINVAL ((eb4) 0)
#define UB4MAXVAL ((ub4) UINT_MAX) #define UB4MINVAL ((ub4) 0)
#define SB4MAXVAL ((sb4) INT_MAX) #define SB4MINVAL ((sb4) INT_MIN)
#define MINEB4MAXVAL ((eb4) 2147483647) #define MAXEB4MINVAL ((eb4) 0) #define MINUB4MAXVAL ((ub4) 4294967295) #define MAXUB4MINVAL ((ub4) 0) #define MINSB4MAXVAL ((sb4) 2147483647) #define MAXSB4MINVAL ((sb4)-2147483647) #else
#ifndef lint
typedef long eb4; typedef unsigned long ub4; typedef signed long sb4; #else
#define eb4 long
#define ub4 unsigned long #define sb4 signed long #endif
#define EB4MAXVAL ((eb4) LONG_MAX) #define EB4MINVAL ((eb4) 0)
#define UB4MAXVAL ((ub4)ULONG_MAX) #define UB4MINVAL ((ub4) 0)
#define SB4MAXVAL ((sb4) LONG_MAX) #define SB4MINVAL ((sb4) LONG_MIN) #define MINEB4MAXVAL ((eb4) 2147483647) #define MAXEB4MINVAL ((eb4) 0)
Trang 24#define MINUB4MAXVAL ((ub4) 4294967295) #define MAXUB4MINVAL ((ub4) 0) #define MINSB4MAXVAL ((sb4) 2147483647) #define MAXSB4MINVAL ((sb4)-2147483647) #endif
#ifndef lint
typedef unsigned long ubig_ora; typedef signed long sbig_ora; #else
#define ubig_ora unsigned long #define sbig_ora signed long #endif
#define UBIG_ORAMAXVAL ((ubig_ora)ULONG_MAX) #define UBIG_ORAMINVAL ((ubig_ora) 0)
#define SBIG_ORAMAXVAL ((sbig_ora) LONG_MAX) #define SBIG_ORAMINVAL ((sbig_ora) LONG_MIN) #define MINUBIG_ORAMAXVAL ((ubig_ora) 4294967295) #define MAXUBIG_ORAMINVAL ((ubig_ora) 0) #define MINSBIG_ORAMAXVAL ((sbig_ora) 2147483647) #define MAXSBIG_ORAMINVAL ((sbig_ora)-2147483647) #define UBIGORABITS (UB1BITS * sizeof(ubig_ora))
#define UB8ZERO ((ub8)0) #define UB8MINVAL ((ub8)0)
#define UB8MAXVAL ((ub8)18446744073709551615) #define MAXUB8MINVAL ((ub8)0)
#define MINUB8MAXVAL ((ub8)18446744073709551615)
Trang 25#if defined(PMAX) && defined( STDC ) # define CONST const
# ifdef M88OPEN # define CONST const # else
# if defined(SEQ_PSX) && defined( STDC ) # define CONST const
Trang 27CHƯƠNG IV : XỬ LÝ PHÁT BIỂU SQL
Sơ đồ các bước xử lý phát biểu SQL
Các bước xử lý SQL:
Trang 28Gọi hàm OCIStmtPrepare() Đây là giai đoạn chuẩn bị cục bộ , ứng dụng có thể dùng hàm OCIAttrGet() (tham số attrtype=OCI_ATTR_STMT_TYPE ) xác định loại phát biểu gì được thực thi
Ở giai đoạn này có thể chuẩn bị phát biểu để thực thi trên nhiều servers cùng một lúcbằng cách liên kết statement handle với các context handle của riêng từng server Khicó liên kết mới được tạo thành thì toàn bộ thông tin về mối liên kết hiện tại giữa servicecontext và statement handle bị mất
Table 4-1 OCI_ATTR_STMT_TYPE Values and Statement Types
Để chương trình trở nên mềm dẻo hơn , chẳng hạn cung cấp dữ liệu vào lúc chạy chương trình , ta thực hiện công việc liên kết nơi chứa dữ liệu với biến chương trình gọi là binding Ví dụ : với phát biểu
INSERT INTO emp(empno) VALUES :num
Ta phải liên kết địa chỉ của biến trong chương trình với nơi chứa ":num" trong phát biểu Binding một nơi chứa là thực hiện một hoặc nhiều bước Đối với kiểu dữ liệu vô hướng đơn hoặc mảng bind thì chỉ cần sử dụng hàm OCIBindByName() hoặc OCIBindByPos()
Liên kết được tạo bởi tên của nơi chứa dữ liệu trong phát biểu gọi là named bind (sử dụng hàm OCIBindByName()) , còn liên kết được tạo bởi vị trí của nơi chứa bắt đầu từ số 1 gọi positional bind (sử dụng hàm OCIBindByPos()) Trong ví dụ trên named bind là ":num" , còn positional bind là 1.
Trong trường hợp cần nạp nhiều giá trị dữ liệu vào database mà chỉ cần một lời gọi hàm đến OCIStmtExecute() phải dùng mảng giao tiếp (array interface) ,khi đó bind một array với một nơi chứa dữ liệu đầu vào và mảng này được nạp cùng lúc vào database dước sự điều khiển của tham số iters
Chú ý rằng các output variable của PL/SQL phải sửng binding chứ không phải defining Bind mảng tĩnh sử dụng hàm OCIBindByPos() hoặc OCIBindByName() rồi sau đó sử dụng hàm OCIBindArrayOfStruct() Khi bind mảng tĩnh phải sử dụng mảng các cấu trúc , đây là đặc tính mới của Oracle8 OCI để hoạt động trên nhiều dòng và nhiều cột Mảng các cấu trúc do người lập trình định nghĩa và khi đó người lập trình phải xác định tham số nhảy (skip parameter)
Trang 29OCI hổ trợ mệnh đề RETURNING cho các phát biểu INSERT ,UPDATE , DALETE để nhận dữ liệu trả về mà không phát biểu khác
Ví dụ :
Với phát biểu
INSERT INTO table1 VALUES (:1, :2, :3,) RETURNING col1, col2, col3
INTO :out1, :out2, :out3
Sau khi dữ liệu được insert thì chúng được trả về thông qua các biến liên kết với các nơi chứa dữ liệu đầu ra.
Phát biểu tiếp theo sẽ cập các giá trị ở các cột col1 ,col2 ,col3 rồi sau đó trả về các giá trị sau khi chúng được sửa đổi
UPDATE table1 SET col1 = col1 + :1, col2 = :2, col3 = :3 WHERE col1 >= :low AND col1 <= :high
RETURNING col1, col2, col3 INTO :out1, :out2, :out3
Phát biểu DELETE sẽ xoá các dòng thoả điều kiện trong mệnh đề WHERE rồi sau đó trả về các giá trị này để kiểm tra
DELETE FROM table1 WHERE col1 >= :low AND col2 <= :high RETURNING col1, col2, col3
INTO :out1, :out2, :out3
Các bước bind các biến trong mệnh đề RETURNING :
1 Bind các nơi chứa trong chế độ OCI_DATA_AT_EXEC dùng hàm OCIBindByPos hoặc OCIBindByName rồi sau đó gọi hàm OCIBindDynamic()
2 Cung cấp hàm bind đầu ra được xem như là tham số ocbfp trong hàm OCIBindDynamic() để nhận dữ liệu trả về
3 Cung cấp hàm giả trả về giá trị NULL khi gọi được xem như là tham icbfp trong hàm OCIBindDynamic()
4 Tham số piecep trong hàm OCIBindDynamic() phải là OCI_ONE_PIECE 5 Không có các bind giống nhau trong phát biểu với mệnh đề RETURNING
III Thực thi phát biểu
Sử dụng hàm OCIStmtExecute() để thực thi một phát biểu đã được prepare Khi truy vấn được thực thi thì ứng có thể cần chuyển đổi dữ liệu sang định dạng của một ngôn ngữ lập trình cụ thể và dữ liệu được trả về trong các biến output hoặc vùng đệm Để nhận dữ liệu trả về cần phải defining một biến output cho mỗi phần tử trong select-list của truy vấn
Đối với phát biểu SELECT nếu các biến output được định nghĩa trước khi gọi hàm OCIStmtExecute() thì phải chỉ rõ số dòng cần nhận trực tiếp vào vùng đệm output thông qua tham số iters
Đối với các phát biểu không phải là truy vấn (INSERT chẳng hạn) thì tham số iters điều khiển phát biểu được bao nhiêu lần
IV Mô tả các phần tử trong danh sách chọn(select-list)
Nếu ứng dụng xử lý một truy vấn mà không biết thông tin về các phần tử trong select-list Trong trường hợp này cần mô tả để nhận datatype và chiều dài của cột
Ví dụ : với truy vấn SELECT * FROM emp;
Trang 30Ta cần phải mô tả nó
Khi mô tả phải gọi hàm OCIStmtExcute() trong chế độ OCI_DESCRIBE_ONLY , ở chế độ này không thực thi phát biểu nhưng sẽ trả về thông tin của các phần tử trong select-list Mô tả không tường minh : để nhận thông tin của các phần tử trong select-list phải gọi
hàm OCIParamGet() cho mỗi phần tử với tham số pos bắt đầu từ 1 cho đến khi OCI_NO_DATA được trả về Một khi tham số descritor được chỉ định thì gọi hàm OCIAttrGet() trên descritor đó để nhận datatype và chiều dài lớn nhất của dữ liệu (riêng kiểu NUMBER thì maxsize=22 được trả về)
Sau đây là ví dụ về mô tả phát biểu (đã được prepare)không tường minh :
parm_status = OCIParamGet(stmthp, OCI_HTYPE_STMT, errhp, &mypard, (ub4) counter); /* Loop only if a descriptor was successfully retrieved for current position, starting at 1 */ while (parm_status==OCI_SUCCESS)
/* Retrieve the data type attribute */
checkerr(errhp, OCIAttrGet((dvoid*) mypard, (ub4) OCI_DTYPE_PARAM, (dvoid*) &dtype,(ub4 *) 0, (ub4) OCI_ATTR_DATA_TYPE, (OCIError *) errhp ));
/* Retrieve the column name attribute */
checkerr(errhp, OCIAttrGet((dvoid*) mypard, (ub4) OCI_DTYPE_PARAM, (dvoid**) &col_name,(ub4 *) &col_name_len, (ub4) OCI_ATTR_NAME, (OCIError *) errhp )); printf("column=%s datatype=%d\n\n", col_name, dtype);
fflush(stdout);
/* increment counter and get next descriptor, if there is one */counter++;parm_status = OCIParamGet(stmthp, OCI_HTYPE_STMT, errhp, &mypard, (ub4) counter);}
Mô tả tường minh : Xem ví dụ :
/* initialize svchp, stmhp, errhp, rowoff, iters, snap_in, snap_out */
Trang 31/* set the execution mode to OCI_DESCRIBE_ONLY Note that setting the mode to OCI_DEFAULT does an implicit describe of the statement in addition to executing the
/* Get the number of columns in the query */
checkerr(errhp, OCIAttrGet(stmhp, OCI_HTYPE_STMT, &numcols, 0, OCI_ATTR_PARAM_COUNT, errh));
/* go through the column list and retrieve the data type of each column We start from pos = 1 */
for (i = 1; i <= numcols; i++){ /* get parameter for column i */
checkerr(errhp, OCIParamGet(stmhp, OCI_HTYPE_STMT, errh, &colhd, i)); /* get data-type of column i */
checkerr(errhp, OCIAttrGet(colhd, OCI_DTYPE_PARAM, &type[i-1], 0, OCI_ATTR_DATA_TYPE, errh)); }
Để nhận dữ liệu trả về phải define một biến output cho mỗi phần tử trong select-list Định nghĩa một biến output là thực hiện một hoặc nhiều bước , dùng hàm OCIDefineByPos() là bước cơ sở
Khi dùng array interface thì ta phải gọi hàm OCIDefineByPos() rồi sau đó gọi hàm OCIDefineArrayOfStruct() (phải thiết lập tham nhảy và chỉ định bao nhiêu dòng được nhận bằng cách thiết lập tham số iters trong hàm OCIStmtExecute()) hoặc hàm OCIDefineObject()(đối với named datatype)
Để nhận một chuỗi dữ liệu động vào lúc thực thi thì dùng hàm OCIDefineByPos() rồi sau đó dùng hàm OCIDefineDynamic()
VI.Nhận dữ liệu
Nếu ứng dụng xử lý truy vấn mà cần nhận dữ liệu trả về sau khi phát biểu được thực thi thì dùng hàm OCIStmtFetch() Nếu ứng dụng chỉ rõ số dòng cần nhận trực tiếp vào biến trong các hoạt động define thì không cần dùng hàm này
Trang 32PHẦN II : CÁC KHÁI NIỆM VỀ OBJECT TRONG OCI
CHƯƠNG V : TỔNG QUAN VỀ LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG TRONG OCI
OCI cho phép truy cập các object từ một Oracle8 server thông qua các phát biểu SQL Thông qua các hàm object navigational của OCI một ứng dụng có thể thực hiện các chức
năng sau : 1 Tạo , truy cập , khóa , xóa ,copy , nạp các object
2 Tham chiếu đến các object và các meta-object của chúng
3 Nhận và thiết lập giá trị các thuộc tính của object một cách động
Ở đây các phát biểu SQL phải sử dụng các hàm về object để tham chiếu và thao tác trên nó Cấu trúc cơ bản của một chương trình theo hướng đối tượng
1 Khởi tạo môi trường lập trình OCI trong chế độ object(OCI_OBJECT) 2 Chỉ định các handle cần thiết và connect đến một server
3 Prepare phát biểu SQL ,đây là bước cục bộ
4 Liên kết phát biểu đã được prepare với một database server và thực thi phát biểu
5 Nhận kết quả trả về Ở bước này sau khi object được pinned thì có thể thực hiện được các việc sau :
Thao tác trên các thuộc tính của object và đánh dấu nó là "dirty" Từ một REF có thể tham chiếu đến các object khác
Truy thông tin về kiểu và thuộc tính Nhận được một sơ đồ object phức hợp Nạp các object được thay đổi đến server
6 Commit transaction , bước này ngầm định nạp tất cả các object đã được thay đổi đến server và ghi nhận những thay đổi này
7 Giải phóng các statement handle và các phát biểu (đã được prepare) mà không được sử dụng lại hoặc thực thi lại
Các bước này sẽ được trình bày chi tiết trong các chương sau
CHƯƠNG VI : OBJECT-RILATIONAL DATATYPEI_Ánh xạ kiểu dữ liệu của Oracle8 sang C
Oracle8 có nhiều kiểu dữ liệu được định nghĩa trước mà dựa vào đó ta có thể tạo ra các bảng và các kiểu khác Các kiểu object mở rộng khả năng của oracle bằng việc cho phép tạo các kiểu dữ liệu một cách chính xác Ví dụ sau tạo ra kiểu địa chỉ do user định nhgĩa và một bảng object chứa các thực thể của kiểu này :
CREATE TYPE address AS OBJECT
CREATE TABLE address_table OF address;
Kiểu address được sử dụng để tạo ra một bảng có một object : CREATE TABLE employees
(name varchar2(30), birthday date,
home_addr address);
Trang 33Một ứng dụng OCI trước tiên biểu diễn các object theo định dạng của ngôn ngữ C Bằng cách sử dụng OTT(Oject Type Translator) để đưa ra cáùu trúc C mô tả các kiểu do user định nghĩa Các phần tử này có các kiểu thực hiện việc ánh xạ sang các kiểu của Oracle8
Bảng 9-1 là danh sách các kiểu của Oracle mà có thể sử dụng như là các kiểu thuộc tính của object và các ánh xạ C
Table 9-1 C Language Mappings of Object Type Attributes
Ngoài ra kiểu OCIInd dùng để chỉ các thuộc tính null của objectPhương pháp ánh xạ các kiểu OCI
Oracle có một số hổ trợ khi ánh xạ các kiểu được định nghĩa trước :
- Thực tế các kliểu dữ liệu như OCINumber là không trong suốt đối với ứng dụng của client , có một tập các hàm được định nghĩa trước để thao tác dữ liệu Điều này cho phép mô tả bên trong thay đổi để tương thích với các nâng cấp trong tương lai
- Việc thực thi là không thay đổi đối với các định hướng đối tuợng chuẩn mà các class che giấu và chỉ khi có hoạt động yêun cầu mới được phô bày
- Việc thực thi như vậy có một số thuận lợi cho lập trình viên Một chương trình C có các biền của Oracle thì không mất tính chính xác Để làm điều này trong Oracle7 dùng phát biểu "SELECT … FROMDUAL" còn trong Oracle8 sử dụng hàm OCINumber*()
II Thao tác các kiểu dữ liệu C với OCI
Xét ví dụ đơn giản cộng hai số nguyên kết quả lưu vào biến thứ 3
Trang 34integer int_1,int_2,sum; …………
Ngôn ngữ C cung cấp một tập các phép toán trên kiểu integer Tuy nhiên các kiểu dữ liệu C
trong bảng 9-1 là không đơn giản như C cổ điển Các kiểu OCIString và OCINumber là các
cấu trúc do Oracle định nghĩa Không thể cộng hai OCINumber và chứa vào OCINumber thứ 3 Ví dụ sau là không hợp lệ :
OCINumber num_1,num_2,sum; …………
Các hàm ánh xạ và thao tác kiểu dữ liệu OCI cho phép thực hiện các phép toán trên các kiểu
dữ liệu mới này Ví dụ dùng hàm OCINumberAdd để cộng 2 OCINumber :
OCINumber num_1,num_2,sum; ………
Table 9-2 Datatype Mapping and Manipulation Function Groups
Tính chính xác của các phép toán trên kiểu Number
Các number của Oracle có 38 số thập phân Tất cả các phép toán number chính xác ngoại trừ :
- Các hàm lượng giác ngược chính xác đến 28 số thập phân
- Các hàm siêu việt , bao gồm các hàm lượng giác , chính xác đến 37 số thập phân - Chuyển đổi các kiểu con trỏ thực thích hợp với kiểu con trỏ thực không vượt quá 38 số thập phân
III Kiểu Date(OCIDate)
Kiểu Date được ánh xạ sang C là kiểu OCIDate là một cấu trúc không trong suốt Các thành phần của cấu trúc Date mô tả năm , tháng , ngày , giờ và giây Để truy các thành phần của kiểu này phải dùng các hàm thích hợp
Kiểu OCIDate có thể được giới hạn và định nghĩa trực tiếp sử dụng mã kiểu SQLT_ODT
Trang 351 Các hàm chuyển đổi date
Table 9-3 Date Conversion Functions
2 Các hàm ấn định và lấy ra
3 Các hàm tính toán và so sánh
Table 9-5 Date Arithmetic and Comparison Functions
4 Các hàm truy cập thông tin kiểu Date
Table 9-6 Date Information Accessor Functions
5 Các hàm kiểm tra tính hiệu lực của Date
Table 9-7 Date Validity Checking Functions
6 Ví dụ
Trang 36Ví dụ sau cho thấy thao trên một thuộc tính của OCIDate như thế nào sử dụng các lời gọi OCI
#define FMT "DAY, MONTH DD, YYYY" #define LANG "American"
OCIDate last_day, next_day;
text buf[100], last_day_buf[100], next_day_buf[100]; ub4 buflen = sizeof(buf);
/* For this example, assume the OCIEnv and OCIError have been * initialized as described in Chapter 2 */
/* Pin tim person object in the object cache See Chapter 6 for * information about pinning For this example, assume that * tim is pointing to the pinned object */
/* set the start date of tim */
OCIDateSetTime(&tim->start_date,8,0,0); OCIDateSetDate(&tim->start_date,1990,10,5) /* check if the date is valid */
if (OCIDateCheck(err, &tim->start_date, &invalid) != OCI_SUCCESS) /* error handling code */
if (invalid)
/* error handling code */
/* get the last day of start_date's month */
if (OCIDateLastDay(err, &tim->start_date, &last_day) != OCI_SUCCESS) /* error handling code */
/* get date of next named day */
if (OCIDateNextDay(err, &tim->start_date, "Wednesday", strlen("Wednesday"), &next_day) != OCI_SUCCESS) /* error handling code */
/* convert dates to strings and print the information out */ /* first convert the date itself*/
buflen = sizeof(buf);
if (OCIDateToText(err, &tim->start_date, FMT, sizeof(FMT)-1, LANG,
/* error handling code */
Trang 37/* now the last day of the month */ buflen = sizeof(last_day_buf);
if (OCIDateToText(err, &last_day, FMT, sizeof(FMT)-1, LANG, sizeof(LANG)-1, &buflen, last_day_buf) != OCI_SUCCESS) /* error handling code */
/* now the first Wednesday after this date */ buflen = sizeof(next_day_out);
if (OCIDateToText(err, &next_day, FMT, sizeof(FMT)-1, LANG, sizeof(LANG)-1, &buflen, next_day_buf) != OCI_SUCCESS) /* error handling code */
/* print out the info */ printf("For: %s\n", buf);
printf("The last day of the month is: %s\n", last_day_buf); printf("The next Wednesday is: %s\n", next_day_buf); The output will be:
For: Monday, May 13, 1996
The last day of the month is: Friday, May 31 The next Wednesday is: Wednesday, May 15
IV Number(OCINumber)
OCINumber là kiểu không trong suốt mô tả các kiểu số NUMBER , FLOAT , DECIMAL Mã kiểu SQLT_VNU
Các hàm thao tác trên OCINumber được liệt kê trong các bảng sau Từ "number" chỉ đến một giá trị kiểu OCINumber
1 Các hàm tính toán
Table 9-8 Number Arithmetic Functions
OCINumberRound() round a number to a specified decimal place
OCINumberTrunc() truncate a number to a specified decimal place
2 Các hàm chuyển đổi
Trang 38Table 9-9 Number Conversion Functions
3 Các hàm logarit và mũ
Table 9-10 Exponential and Logarithmic Functions
4 Các hàm lượng giác
Table 9-11 Trigonometric Functions
5 Các hàm ấn định và so sánh
Table 9-12 Number Assignment and Comparison Functions
Trang 39OCINumberSetZero() initialize number to zero
/* For this example, assume OCIEnv and OCIError are initialized */ /* For this example, assume that steve, scott and jason are pointing to person objects which have been pinned in the object cache */
if (status != OCI_SUCCESS) /* handle error from OCINumberFromInt */; /* initialize scott's salary to be same as steve */
OCINumberAssign(err, stevesal, scottsal);
/* initialize jason's salary to be 20% more than steve's */ dnum = 1.2;
status = OCINumberFromReal(err, &dnum, DBL_DIG, &ornum);
if (status != OCI_SUCCESS) /* handle error from OCINumberFromReal */; status = OCINumberMul(err, stevesal, &ornum, debsal);
if (status != OCI_SUCCESS) /* handle error from OCINumberMul */; /* give scott a 50% raise */
Trang 40dnum = 1.5;
status = OCINumberFromReal(err, &dnum, DBL_DIG, &ornum);
if (status != OCI_SUCCESS) /* handle error from OCINumberFromReal */; status = OCINumberMul(err, scottsal, &ornum, scottsal);
if (status != OCI_SUCCESS) /* handle error from OCINumberMul */; /* double steve's salary */
status = OCINumberAdd(err, stevesal, stevesal, stevesal);
if (status != OCI_SUCCESS) /* handle error from OCINumberAdd */; /* get steve's salary in integer */
status = OCINumberToInt(err, stevesal, sizeof(inum), OCI_NUMBER_SIGNED, &inum);
if (status != OCI_SUCCESS) /* handle error from OCINumberToInt */; /* inum is set to 24000 */
/* get jason's salary in double */
status = OCINumberToReal(err, debsal, sizeof(dnum), &dnum);
if (status != OCI_SUCCESS) /* handle error from OCINumberToReal */;
if (status != OCI_SUCCESS) /* handle error from OCINumberToText */; printf("scott's salary = %s\n", buffer);
/* compare steve and scott's salary */
status = OCINumberCmp(err, stevesal, scottsal, &result);
if (status != OCI_SUCCESS) /* handle error from OCINumberCmp */; /* result is positive */
/* read jason's new salary from string */
status = OCINumberFromText(err, "48\Q000.00", 9, "99G999D99", 9, "NLS_NUMERIC_CHARACTERS='.\Q'", 27, debsal);
if (status != OCI_SUCCESS) /* handle error from OCINumberFromText */; /* jason's salary is now 48000.00 */
V String có chiều dài thay đổi hoặc cố định (OCIString)
Chiều dài chuỗi có thể thay đổi hoặc cố định được hiện thực trong C là OCIString* Chiềudài chuỗi không bao gồm ký tự null
Mã kiểi là SQLT_VST1 String Function
Table 9-13 String Functions
OCIStringAssignText() assign text string to string
OCIStringAllocSize() get allocated size of string memory in bytes