一、優點
1、大家知道 Delphi 對 ADO 接口進行了一番包裝後形成了 ADOExpress,我想 Borland 的主要目的還是想與自己的數據敏感控件相連。然而事實上數據敏感控件並不是那麼耀眼,如果你希望你編出來的程序稍微有點水準的話那就別用那玩意;如果你很少使用數據敏感控件,那麼 ADOExpress 基本上失去了其應有的作用,無數冗餘的屬性、虛方法,不管你用不用得到一股腦給你編譯進去,也會使你的程序再大上 200K;效率麼,不說了。
2、MSDN 和 VB 中的例子你可以搬過來就用。
3、告訴那些 Delphi 反對者,Delphi 不是離開組件就活不了。
4、關於代碼重用:我給大家的例子都是以函數或過程形式,重用性不好麼?
5、別說帖子太長,那你看看 DB.pas, ADODB.pas 多長?
二、基本儲備
1、一些必須的單元
uses
Variants, ComObj;
2、一些基本常數(其它查 ADODB2000.pas):
const
adOpenDynamic = $00000002;
adOpenStatic = $00000003;
adLockOptimistic = $00000003;
adLockBatchOptimistic = $00000004;
adStateClosed = $00000000;
adStateOpen = $00000001;
adStateConnecting = $00000002;
adStateExecuting = $00000004;
adStateFetching = $00000008;
adUseServer = $00000002;
adUseClient = $00000003;
adModeReadWrite = $00000003;
adXactCursorStability = $00001000;
adCmdText = $00000001;
adCmdTable = $00000002;
adCmdStoredProc = $00000004;
adCmdFile = $00000100;
adAffectCurrent = $00000001;
adAffectGroup = $00000002;
adAffectAll = $00000003;
adAffectAllChapters = $00000004;
3、一些基本函數和過程
//創建 Connection 對象
function CreateConnection: OleVariant;
//釋放 Connection 對象;cnn 爲 Connection 對象
procedure FreeConnection(var cnn: OleVariant);
//創建 Recordset 對象
function CreateRecordset: OleVariant;
//釋放 Recordset 對象;rst 爲 Recordset 對象
procedure FreeRecordset(var rst: OleVariant);
//創建 Command 對象
function CreateCommand: OleVariant;
//釋放 Command 對象;cmd 爲 Command 對象
procedure FreeCommand(var cmd: OleVariant);
//用 Connection 連接到 SQLServer 數據庫;cnn 爲 Connection 對象,db 數據庫名,host 主機名,usr 用戶名,pwd 密碼
function ConnectToDB(cnn: OleVariant; const db, host, usr, pwd: string): Boolean;
//執行 SQL 語句,有返回行,無事務處理;cnn 爲 Connection 對象,rst 爲 Recordset 對象,sql 爲 SQL 語句(可以是存儲過程)
function ExecSQL(cnn, rst: OleVariant; const sql: string): Boolean;
//執行 SQL 語句,無返回行,有事務處理;cnn 爲 Connection 對象,cmd 爲 Command 對象,sql 爲 SQL 語句(可以是存儲過程)
function ExecSQLA(cnn, cmd: OleVariant; const sql: string): Boolean;
function CreateConnection: OleVariant;
begin
try
Result := CreateOleObject('ADODB.Connection');
Result.CursorLocation := adUseServer;
Result.IsolationLevel := adXactCursorStability;
Result.Mode := adModeReadWrite;
Result.Provider := 'SQLOLEDB.1';
except
if not VarIsEmpty(Result) then Result := Unassigned;
end;
end;
procedure FreeConnection(var cnn: OleVariant);
begin
if not VarIsEmpty(cnn) then
begin
if cnn.State <> adStateClosed then cnn.Close;
cnn := Unassigned;
end;
end;
function CreateRecordset: OleVariant;
begin
try
Result := CreateOleObject('ADODB.Recordset');
Result.CacheSize := 1000;
Result.CursorType := adOpenStatic;
Result.CursorLocation := adUseServer;
Result.LockType := adLockOptimistic;
except
if not VarIsEmpty(Result) then Result := Unassigned;
end;
end;
procedure FreeRecordset(var rst: OleVariant);
begin
FreeConnection(rst);
end;
function CreateCommand: OleVariant;
begin
try
Result := CreateOleObject('ADODB.Command');
Result.CommandType := adCmdText;
Result.CommandTimeout := 5;
except
if not VarIsEmpty(Result) then Result := Unassigned;
end;
end;
procedure FreeCommand(var cmd: OleVariant);
begin
if not VarIsEmpty(cmd) then cmd := Unassigned;
end;
function ConnectToDB(cnn: OleVariant; const db, host, usr, pwd: string): Boolean;
begin
Result := not VarIsEmpty(cnn);
if Result then
begin
if cnn.State <> adStateClosed then cnn.Close;
cnn.ConnectionString :=
'Provider=SQLOLEDB.1;Persist Security Info=True;Initial Catalog=' +
db + ';Data Source=' + host + ';Connect Timeout=5;' +
'Use Procedure for Prepare=1';
try
cnn.Open(cnn.ConnectionString, usr, pwd, -1);
except
Result := False;
end;
end;
end;
function ExecSQL(cnn, rst: OleVariant; const sql: string): Boolean;
begin
Result := not (VarIsEmpty(cnn) or VarIsEmpty(rst)) and (cnn.State = adStateOpen);
if Result then
begin
if rst.State <> adStateClosed then rst.Close;
try
rst.Open(sql, cnn, adOpenStatic, adLockOptimistic, adCmdText);
except
Result := False;
end;
end;
end;
function ExecSQLA(cnn, cmd: OleVariant; const sql: string): Boolean;
begin
Result := not (VarIsEmpty(cnn) or VarIsEmpty(cmd)) and (cnn.State = adStateOpen);
if Result then
begin
cnn.BeginTrans;
try
cmd.ActiveConnection := cnn;
cmd.CommandText := sql;
cmd.Prepared := True;
cmd.Execute;
cnn.CommitTrans;
except
cnn.RollbackTrans;
Result := False;
end;
end;
end;
三、訪問數據
1、最前 rst.MoveFirst;
2、最後 rst.MoveLast;
3、向前 rst.MovePrevious;
4、向後 rst.MoveNext;
5、取當前記錄 rst.Fields[0].Value 或 rst.Fields['字段名'].Value;
6、修改當前記錄 rst.Update(rst.Fields[0].Name, 某值);
7、取消修改 rst.CancelUpdate;
8、刪除當前記錄 rst.Delete(adAffectCurrent);
9、刪除所有記錄 rst.Delete(adAffectAll);
10、追加記錄
rst.AddNew;
rst.Fields[0].Value := 值1;
rst.Fields[1].Value := 值2;
rst.Update;
11、刷新 rst.Refresh;
12、記錄數 rst.RecordCount
15、其它方法和屬性查 MSDN 或 ADO 的幫助;
四、一些例子
//變量聲明
var
cnn, rst, cmd: OleVariant;
//創建對象
procedure TForm1.FormCreate(Sender: TObject);
begin
cnn := CreateConnection;
rst := CreateRecordset;
cmd := CreateCommand;
end;
//釋放對象
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeCommand(cmd);
FreeRecordset(rst);
FreeConnection(cnn);
end;
//連接數據庫
procedure TForm1.Button1Click(Sender: TObject);
begin
if ConnectToDB(cnn, 'mydb', '127.0.0.1', 'sa', 'ok') then
Caption := '連接成功'
else Caption := '連接失敗';
end;
//取記錄
procedure TForm1.Button2Click(Sender: TObject);
begin
ExecSQL(cnn, rst, 'select * from 表a');
Caption := VarToStr(rst.Fields['字段a'].Value);
end;
五、原生 ADO 與 Delphi ADOExpress 組件的對應關係
1、Connection <=> ADOConnection.ConnectionObject;
2、Recordset <=> ADODataSet.Recordset;
3、Command <=> ADOCommand.CommandObject;
4、? <=> ADOQuery,因爲 ADOQuery 根本就不是原生 ADO 對象
5、ExecSQL <=> ADODataSet.Open;
6、ExecSQLA <=> ADOCommand.Execute;
7、有了上面幾個其它的就不多說了
六、與數據庫結構有關的一些函數
1、動態改變字段名稱
uses ComObj;
//Access
//TableName: 表名; OldColName: 原字段名; NewColName: 新字段名;
procedure RenameField(const TableName, OldColName, NewColName: string);
var
DB, Col: OleVariant;
begin
DB := CreateOleObject('ADOX.Catalog');
DB.ActiveConnection := ADOConnection1.ConnectionObject;
Col := CreateOleObject('ADOX.Column');
Col := DB.Tables[TableName].Columns[OldColName];
Col.Name := NewColName;
end;
//SQLServer
procedure RenameField(const TableName, OldColName, NewColName: string);
begin
with ADOCommand1 do
begin
CommandText := 'EXEC sp_rename ''' + TableName + '.' + OldColName +
''',''' + NewColName + ''',''COLUMN'';';
Excute;
end;
end;
2、取得 Access 庫中的表結構
type
TTableDef = record
Name,
DateCreated,
LastUpdated,
Description: string;
end;
TTableDefs = array of TTableDef;
procedure GetTableDefs(const DBName: string; out TableDefs: TTableDefs);
var
DBEngine, DB: OleVariant;
I: Longint;
begin
try
DBEngine := CreateOleObject('DAO.DBEngine.36');
DB := DBEngine.OpenDatabase(DBName);
SetLength(TableDefs, Longint(DB.TableDefs.Count));
for I := Low(TableDefs) to High(TableDefs) do
begin
TableDefs[I].Name := DB.TableDefs[I].Name;
TableDefs[I].DateCreated := DB.TableDefs[I].DateCreated;
TableDefs[I].LastUpdated := DB.TableDefs[I].LastUpdated;
try
TableDefs[I].Description := DB.TableDefs[I].Properties['Description'].Value;
except
TableDefs[I].Description := '';
end;
end;
finally
DB := Unassigned;
DBEngine := Unassigned;
end;
end;
3、取得 Access 表中的字段結構
type
TFieldDef = record
Name: string;
Types,
Size: Longint;
Description: string;
end;
TFieldDefs = array of TFieldDef;
procedure GetFieldDefs(const DBName, TableName: string; out FieldDefs: TFieldDefs);
var
DBEngine, DB: OleVariant;
I: Longint;
begin
try
DBEngine := CreateOleObject('DAO.DBEngine.36');
DB := DBEngine.OpenDatabase(DBName);
SetLength(FieldDefs, Longint(DB.TableDefs[TableName].Fields.Count));
for I := Low(FieldDefs) to High(FieldDefs) do
begin
FieldDefs[I].Name := DB.TableDefs[TableName].Fields[I].Name;
FieldDefs[I].Types := DB.TableDefs[TableName].Fields[I].Type;
FieldDefs[I].Size := DB.TableDefs[TableName].Fields[I].Size;
try
FieldDefs[I].Description := DB.TableDefs[TableName].Fields[I].Properties['Description'].Value;
except
FieldDefs[I].Description := '';
end;
end;
finally
DB := Unassigned;
DBEngine := Unassigned;
end;
end;
4、至於如何動態創建 Access 數據庫之類我就不羅嗦了,到處都有相關的月經貼
七、其它
1、我使用 ADO 的經歷:ADOExpress-->ADOExpress的原生接口-->引用ADO2.1接口單元,即ADODB_TLB-->直接使用 ADO 的 COM 接口;
2、希望此貼能對朋友門有所幫助,我寫的這些都是經過實戰檢驗的;
3、覺得有用的朋友可以試一下,如果覺得沒用就當我沒寫,耽誤你時間了。