一点心得:在 Delphi 中使用原生 ADO 控制数据库

4 篇文章 0 订阅

http://www.delphibbs.com/delphibbs/dispq.asp?lid=3047846

我发现很多朋友在开发数据库时都使用 Delphi 自带的 ADO 组件 或 Diamond ADO,其实在 Delphi 中使用原生 ADO 接口也是十分方便和有效的。我使用原生 ADO 开发项目已有很长一段时间,也回答过一些朋友类似的问题,现在把自己的一点心得与大家分享,班门弄斧,只是希望能对大家有所帮助。当然,这帖子也是原生的,不是转贴的。

一、优点
1、大家知道 Delphi 对 ADO 接口进行了一番包装后形成了 ADOExpress,我想 Borland 的主要目的还是想与自己的数据敏感控件相连。然而事实上数据敏感控件并不是那么耀眼,如果你希望编出来的程序稍微有点水准的话就别用那玩意;如果你很少使用数据敏感控件,那么 ADOExpress 基本上失去了其应有的作用,无数冗余的属性、虚方法,不管你用不用得到一股脑给你编译进去,也会使你的程序再大上 200K;效率么,不说了。
2、MSDN 和 VB 中的例子你可以搬过来就用。
3、关于代码重用:我给大家的例子都是以函数或过程形式,重用性不好么?
4、别说帖子太长,那你看看 DB.pas, ADODB.pas 多长?

二、基本储备
1、一些必须的单元
uses
  Variants, ComObj;

2、一些基本常数(其它查 ADODB2000.pas 或搜索 adovbs.inc):
const
  adOpenDynamic = $00000002;
  adOpenStatic = $00000003;

  adLockOptimistic = $00000003;
  adLockBatchOptimistic = $00000004;

  adConnectUnspecified = $FFFFFFFF;
  adAsyncConnect = $00000010;

  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;

  adEmpty = $00000000; //空
  adInteger = $00000003; //长整
  adSingle = $00000004; //单精
  adDouble = $00000005; //双精
  adCurrency = $00000006; //货币
  adGUID = $00000048; //全球唯一的标志码
  adDate = $00000007; //日期
  adDBDate = $00000085; //日期值(yyyymmdd)
  adDBTime = $00000086; //时间值(hhmmss)
  adDBTimeStamp = $00000087; //日期时间值(yyyymmdd hhmmss)
  adBoolean = $0000000B; //布尔
  adVarChar = $000000C8; //字符串
  adVarWChar = $000000CA; //文本
  adLongVarWChar = $000000CB; //备注

//存储过程参数结构,只定义了常用的部分,如果需要自己加吧
type
  TParameter_ = record
    Name: WideString;
    Type_: LongWord;
    Direction: LongWord;
    Size: Longint;
    Value: OleVariant;
  end;

  TParameters_ = array of TParameter_;

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 对象,srv 主机名或 IP 地址,uid 用户名,pwd 密码,db 数据库名
function ConnectToDB(cnn: OleVariant; const srv, uid, pwd, db: 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;
//执行存储过程;cnn 为 Connection 对象,cmd 为 Command 对象,rst 为 Recordset 对象(用于接收来自存储过程的数据集);prc 为存储过程名; prms 为参数集合
function ExecProc(cnn, cmd, rst: OleVariant; const prc: string; prms: TParameters_): 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 srv, uid, pwd, db: 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=' + srv + ';Connect Timeout=10;' +
      'Use Procedure for Prepare=1';
    try
      cnn.Open(cnn.ConnectionString, uid, pwd, adConnectUnspecified);
    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;

function ExecProc(cnn, cmd, rst: OleVariant; const prc: string; prms: TParameters_): Boolean;
var
  i: Longint;
begin
  Result := not (VarIsEmpty(cnn) or VarIsEmpty(cmd)) and (cnn.State = adStateOpen);
  if Result then
  begin
    try
      cmd.CommandText := prc;
      cmd.CommandType := adCmdStoredProc;
      cmd.ActiveConnection := cnn;

      //之前,将我们自己的参数集合中的输入参数添入 Command 参数集合
      for i := Low(prms) to High(prms) do
        case prms[i].Direction of
          //未知类型的参数(adParamUnknown)既不算作输入参数也不算作输出参数
          adParamInput, adParamInputOutput:
            cmd.Parameters[prms[i].Name].Value := prms[i].Value;
        end;

      rst := cmd.Execute;

      //之后,将输出参数从 Command 参数集合读取到我们自己的参数集合
      for i := Low(prms) to High(prms) do
        case prms[i].Direction of
          //未知类型的参数(adParamUnknown)既不算作输入参数也不算作输出参数
          adParamOutput, adParamInputOutput:
            prms[i].Value := cmd.Parameters[prms[i].Name].Value;
          adParamReturnValue:
            prms[i].Value := cmd.Parameters[0].Value;
        end;
    except
      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, '127.0.0.1', 'sa', 'ok', 'Northwind') then
    Caption := '连接成功'
  else Caption := '连接失败';
end;

//取记录
procedure TForm1.Button2Click(Sender: TObject);
begin
  if ExecSQL(cnn, rst, 'SELECT * FROM Products') then
    Caption := VarToStr(rst.Fields['ProductName'].Value);
end;

//执行存储过程
(*
CREATE PROCEDURE GetProductName
    @ProductID int,
    @ProductName varchar(50) OUTPUT
AS
SELECT @ProductName = ProductName
FROM Products
WHERE ProductID = @ProductID
RETURN @ProductID
*)
procedure TForm1.Button3Click(Sender: TObject);
var
  prms: TParameters_;
begin
  SetLength(prms, 3);
  //参数 0 接收返回值;Name 取什么都行,但 Direction 必须标明为adParamReturnValue
  prms[0].Name := '@RETURN_VALUE';
  prms[0].Direction := adParamReturnValue;
  //参数 1 作为输入参数,Name 必须与实际参数名相同,Direction 标明 adParamInput
  prms[1].Name := '@ProductID';
  prms[1].Direction := adParamInput;
  prms[1].Value := 8;
  //参数 2 作为输出参数,Name 必须与实际参数名相同,Direction 标明 adParamOutput
  prms[2].Name := '@ProductName';
  prms[2].Direction := adParamOutput;
  //执行存储过程;如果不需要 Recordset 对象接收返回的数据集,就把它置空
  ExecProc(cnn, cmd, Null, 'GetProductName', prms);
  ShowMessage(prms[0].Value);
  ShowMessage(prms[2].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
  cat, col: OleVariant;
begin
  cat := CreateOleObject('ADOX.Catalog');
  cat.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、不用 SQL 语句,仅用 ADOX,创建 Access 数据库、表、字段、字段备注(同样适用于 SQLServer)
function CreateMDB(const DBName, TableName: string): Boolean;
var
  cat, tbl, col: OleVariant;
begin
  Result := True;
  try
    try
      //生成数据库
      cat := CreateOleObject('ADOX.Catalog');
      cat.Create('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=' + DBName);

      //生成表
      tbl := CreateOleObject('ADOX.Table');
      tbl.ParentCatalog := cat;
      tbl.Name := TableName;

      //生成一个带备注、自动编号的长整字段
      col := CreateOleObject('ADOX.Column');
      col.ParentCatalog := cat;
      col.Name := '带自动编号的长整字段';
      col.Type := adInteger;
      col.DefinedSize := 4;
      //自动编号字段就是长整字段,仅仅多了下面这句话
      col.Properties['Autoincrement'].Value := True;
      col.Properties['Description'].Value := '自动编号长整字段的说明';
      tbl.Columns.Append(col, adEmpty, 0);
      col := Unassigned;
      //生成一个带备注的文本字段
      col := CreateOleObject('ADOX.Column');
      col.ParentCatalog := cat;
      col.Name := '文本字段';
      col.Type := adVarWChar;
      col.DefinedSize := 50;
      col.Properties['Description'].Value := '文本字段的说明';
      tbl.Columns.Append(col, adEmpty, 0);
      //生成一个不带备注的双精字段,比上面要简单的多
      tbl.Columns.Append('双精字段', adDouble, 8);
      //生成一个不带备注的备注字段
      tbl.Columns.Append('备注字段', adLongVarWChar, 16);

      cat.Tables.Append(tbl);
    except
      Result := False;
    end;
  finally
    cat := Unassigned;
    tbl := Unassigned;
    col := Unassigned;
  end;
end;

七、进行分页显示数据
俺们几乎每天都见到网页用 ADO 进行分页(每次只取一定数量的记录),但是在 Delphi 中分页也成了稀罕的东西 :(
分页有三个常用的属性:PageSize—页面大小,PageCount—页面总数,AbsolutePage—决定跳转到哪一页面。
1、首先取得数据集,不罗嗦了
ADODataSet1.Open....
2、下面这个例子,将指定页面的数据读到 Memo1 中
procedure GetPageData(const nPage: Integer);
var
  i: Integer;
begin
  wiht ADODataSet1.Recordset do
  begin
    if (State = adStateClosed) or (nPage < 1) or (nPage > PageCount) then Exit;
    Memo1.Clear;
    AbsolutePage := nPage;
    //这里只能用 for 不能用 while(Eof 仍然表示数据集的结尾)
    for i := 1 to PageSize do
    begin
      Memo1.Lines.Add(Fields['ProductName'].Value);
      MoveNext;
      //防止因最后一页未满而产生越界
      if Eof then Exit;
    end;
  end;
end;

八、其它
1、希望此贴能对朋友们有所帮助,我写的这些都是经过实战检验的;
2、觉得有用的朋友可以试一下,如果觉得没用就当我没写,耽误你时间了。

 

To guosoong:
你说的是备注型字段还是字段的备注?得了,一起给你写出来好了。当然,如你所愿,创建数据库、表、字段不用 SQL 语句,就用 ADOX。
uses ComObj;

const
  adEmpty = $00000000;  //空
  adInteger = $00000003; //长整
  adSingle = $00000004; //单精
  adDouble = $00000005; //双精
  adCurrency = $00000006; //货币
  adVarWChar = $000000CA; //文本
  adLongVarWChar = $000000CB; //备注

function CreateMDB(const DBName, TableName: string): Boolean;
var
  cat, tbl, col: OleVariant;
begin
  Result := True;
  try
    try
      cat := CreateOleObject('ADOX.Catalog');
      cat.Create('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=' + DBName);

      tbl := CreateOleObject('ADOX.Table');
      tbl.ParentCatalog := cat;
      tbl.Name := TableName;

      //生成一个带备注的长整字段
      col := CreateOleObject('ADOX.Column');
      col.ParentCatalog := cat;
      col.Name := '长整字段';
      col.Type := adInteger;
      col.DefinedSize := 4;
      col.Properties['Description'].Value := '长整字段的说明';
      tbl.Columns.Append(col, adEmpty, 0);
      col := Unassigned;
      //生成一个带备注的文本字段
      col := CreateOleObject('ADOX.Column');
      col.ParentCatalog := cat;
      col.Name := '文本字段';
      col.Type := adVarWChar;
      col.DefinedSize := 50;
      col.Properties['Description'].Value := '文本字段的说明';
      tbl.Columns.Append(col, adEmpty, 0);
      //生成一个不带备注的双精字段,比上面要简单的多
      tbl.Columns.Append('双精字段', adDouble, 8);
      //这个就是你要的备注字段
      tbl.Columns.Append('备注字段', adLongVarWChar, 16);

      cat.Tables.Append(tbl);
    except
      Result := False;
    end;
  finally
    cat := Unassigned;
    tbl := Unassigned;
    col := Unassigned;
  end;
end;  
我終于搞定了,vvyang謝謝啦
獻上整個單元供大家指導我,小的在這裡抛磚引玉了。

鬱悶了好久,終于搞定了。哈哈
獻上整個函數單元供大家參考;


unit DatabaseUnit;

interface
uses  Windows, Messages, SysUtils, Variants, Classes,comobj,DB,ADODB,Controls;






procedure CreateDatabase(DBName: string); //建立Access数据库
Procedure _CreateDatabaseTable(DBName: string; Tablenames:Tstrings; FieldDefsListArray: array of Tlist; arraycount: integer); //建立Access数据库中的表
procedure GetTableDefs(const DBName: string; TableDefsList: Tlist);              //获得Access数据库中的表信息
procedure GetFieldDefs(const DBName, TableName: string; FieldDefsList: Tlist);  //获得Access数据库中的每个表中的字段信息
procedure RenameField(const TableName, OldColName, NewColName: string; ADOConnection:TADOConnection ); //动态修改Access数据库字段内容
function CheckTablename(Const DBName, TableName: string): boolean;
implementation

uses VariableUnit;

procedure CreateDatabase(DBName: string);      //建立access数据库
var
  DB: OleVariant;
  tempstr: string;    
begin
  DB := CreateOleObject('ADOX.Catalog');
  try
    tempstr := format(accessstring,[DBName]);
    DB.Create(tempstr);
  finally
    DB:=Unassigned;
  end;
end;

Procedure _CreateDatabaseTable(DBName: string; Tablenames:Tstrings; FieldDefsListArray: array of Tlist; arraycount: integer); //建立Access数据库中的表
var
  DB,tables,Cols: OleVariant;    //DBEngine,
  temploop1,temploop2: integer;
  temppointer: pTAccessFieldDef;
  tempADOConnection:TADOConnection;
  tempstr: string;
begin
  if not FileExists(DBName) then  //如果没有发现数据库就建立数据库
  CreateDatabase(DBName);
  if TableNames.Count <= 0 then exit;
  if TableNames.Count <> arraycount then exit; //名称和字段信息个数不一致,就退出

//  DBEngine := CreateOleObject('DAO.DBEngine.36');
  //DB := DBEngine.OpenDatabase(DBName);

  DB := CreateOleObject('ADOX.Catalog');
  tempADOConnection := TADOConnection.Create(nil);
  tempstr := format(accessstring,[DBName]);
  tempADOConnection.ConnectionString := tempstr;
  tempADOConnection.Open;
  DB.ActiveConnection := tempADOConnection.ConnectionObject;

  try
  for temploop1 := 0 to TableNames.Count -1 do
  begin
    if CheckTablename(DBName,TableNames[temploop1]) then //如果没有同名就建立
    begin
      tables := CreateOleObject('ADOX.Table');

      tables.ParentCatalog := DB;
      tables.name := TableNames[temploop1]; //表建立好之后,就开始建立字段
      if FieldDefsListArray[temploop1].Count > 0 then
      begin
        for temploop2 := 0 to FieldDefsListArray[temploop1].Count -1 do
        begin
          temppointer := FieldDefsListArray[temploop1].Items[temploop2];
          Cols := CreateOleObject('ADOX.Column');
          Cols.ParentCatalog := DB;
          case temppointer.Types of
            adInteger: begin
                          Cols.Name := temppointer.Name;
                          Cols.type := temppointer.Types;
                          Cols.DefinedSize := temppointer.Size;
                          Cols.Properties['Autoincrement'].Value := strtobool(temppointer.Autoincrement);
                          Cols.Properties['Description'].Value := temppointer.Description;
                          tables.Columns.Append(Cols, adEmpty, 0);
                          Cols := Unassigned;
                        end;
            adVarWChar: begin
                          Cols.Name := temppointer.Name;
                          Cols.type := temppointer.Types;
                          Cols.DefinedSize := temppointer.Size;
                          Cols.Properties['Description'].Value := temppointer.Description;
                          tables.Columns.Append(Cols, adEmpty, 0);
                          Cols := Unassigned;
                        end;
            adLongVarWChar: begin
                              Cols.Name := temppointer.Name;
                              Cols.type := temppointer.Types;
                              Cols.DefinedSize := temppointer.Size;
                              Cols.Properties['Description'].Value := temppointer.Description;
                              tables.Columns.Append(Cols, adEmpty, 0);
                              Cols := Unassigned;
                            end;
          end;  //case temppointer.Types of

        end; //for temploop2 := 0 to FieldDefsListArray[temploop1].Count -1 do

        DB.Tables.Append(tables);
        tables:= Unassigned;      //每个表的所有字段都建立好之后,就注销,进入下一个表
        Cols:=  Unassigned;
      end
      else    //if FieldDefsListArray[temploop1].Count > 0 then 如果字段小于等于0 就不要建立这个表的字段,
      begin                                                     //进入下一张表
        tables:= Unassigned;
        Cols:=  Unassigned;
      end;


    end   //if CheckTablename(DBName,TableNames[temploop1]) then //如果没有同名就建立
  end;   //for temploop1 := 0 to TableNames.Count -1 do
  finally
    //DBEngine:= Unassigned;
    tempADOConnection.Close;
    DB:= Unassigned;
    tables:= Unassigned;
    Cols:=  Unassigned;
    tempADOConnection.Free;
  end;

end;


procedure GetTableDefs(const DBName: string; TableDefsList: Tlist);  //获得Access数据库中的表信息
var
  DBEngine, DB: OleVariant;
  I: Longint;
  temppointer: pTaccessTableDef;
begin
  try
    DBEngine := CreateOleObject('DAO.DBEngine.36');
    DB := DBEngine.OpenDatabase(DBName);
    if Longint(DB.TableDefs.Count) > 0 then
    begin
      for I := 0 to Longint(DB.TableDefs.Count)-1 do
      begin
        new(temppointer);
        temppointer.Name := DB.TableDefs[I].Name;
        temppointer.DateCreated := DB.TableDefs[I].DateCreated;
        temppointer.LastUpdated := DB.TableDefs[I].LastUpdated;
        try
          temppointer.Description := DB.TableDefs[I].Properties['Description'].Value;
        except
          temppointer.Description := '';
        end;
        TableDefsList.Add(temppointer);
      end; //for I := 0 to Longint(DB.TableDefs.Count)-1 do
    end; // if Longint(DB.TableDefs.Count) > 0 then
  finally
    DB := Unassigned;
    DBEngine := Unassigned;
  end;
end;


procedure GetFieldDefs(const DBName, TableName: string; FieldDefsList: Tlist); //获得Access数据库中的每个表中的字段信息
var
  DBEngine, DB: OleVariant;
  I: Longint;
  temppointer: pTAccessFieldDef;
begin
  try
    DBEngine := CreateOleObject('DAO.DBEngine.36');
    DB := DBEngine.OpenDatabase(DBName);
    if Longint(DB.TableDefs[TableName].Fields.Count) > 0 then
    begin
      for I := 0 to Longint(DB.TableDefs[TableName].Fields.Count) -1 do
      begin
        new(temppointer);
        temppointer.Name := DB.TableDefs[TableName].Fields[I].Name;
        temppointer.Types := DB.TableDefs[TableName].Fields[I].Type;
        temppointer.Size := DB.TableDefs[TableName].Fields[I].Size;
        try
          temppointer.Description := DB.TableDefs[TableName].Fields[I].Properties['Description'].Value;
        except
          temppointer.Description := '';
        end;
        FieldDefsList.Add(temppointer);
      end;   //Longint(DB.TableDefs[TableName].Fields.Count) > 0
    end; // Longint(DB.TableDefs[TableName].Fields.Count) > 0
  finally
    DB := Unassigned;
    DBEngine := Unassigned;
  end;
end;


//TableName: 表名; OldColName: 原字段名; NewColName: 新字段名;
procedure RenameField(const TableName, OldColName, NewColName: string; ADOConnection:TADOConnection );
var
  DB, Col: OleVariant;
begin
try
  DB := CreateOleObject('ADOX.Catalog');
  DB.ActiveConnection := ADOConnection.ConnectionObject;
  Col := CreateOleObject('ADOX.Column');
  Col := DB.Tables[TableName].Columns[OldColName];
  Col.Name := NewColName;
  finally
    DB := Unassigned;
    Col := Unassigned;
  end;
end;


function CheckTablename(Const DBName, TableName: string): boolean;  //true 表示没有检测到相同表名,就可以建立,
var                                                                 //false 表示检测到相同表名,不可以建立
  tableNamelist: Tlist;
  temploop: integer;
  temppointer: pTaccessTableDef;
begin
  result := false;
  if not FileExists(DBName) then
  CreateDatabase(DBName);

  tableNamelist := Tlist.Create;
  try
    GetTableDefs(DBName,tableNameList);
    if tableNamelist.Count > 0 then
    begin
      for temploop := 0 to TableNameList.Count -1 do
      begin
        temppointer := TableNamelist.Items[temploop];
        if UpperCase(tableName) = UpperCase(temppointer.Name) then
        exit;
      end;
    end;
    result := true;   //如果里面没有表也可以返回true
  finally
    tableNamelist.Clear;
    tablenamelist.Free;
  end;
end;

end.  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值