用Delphi实现不同数据库系统之间的数据转移在计算机应用系统的软件升级改造过程中,我们经常遇到这样一个问题:老系统的数据库平台与新系统不同。例如,老系统的数据库平台是Foxpro,而新系统的平台是SQL Server。而且,我们需要把旧的数据库应用系统中的一些数据转移到新系统来。但是因为新老系统在定义数据类型、数据格式等方面的差异,就很难用人工录入的方法来实现。因此,需要有一个能实现这种功能的程序。本文利用Borland Delphi实现了这个转移过程。基本思想是:在一个Form中,分别用两个TDatabase控件连接新老数据库。并采用TTable、TDbGrid作为数据转移的中心,根据DbGrid中的数据生成标准的SQL插入语句。这样,就实现了从一个数据库系统到另一个数据库系统的数据转移。在这里,采用TTable、TDbGrid作为数据转移的中心是一个技巧,因为:TTable的Fields属性能指示出某字段的字段名称、数据类型等,这为数据转移过程中的Insert语句的生成及数据类型转换提供了依据。下面的例子展示了从Foxpro到SQL Server的数据转移方法。至于其他系统间的数据转移,只要根据目标系统的数据定义要求,修改相应的Insert语句。程序代码如下:unit ConvertDBF;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DBTables, Db, Grids, DBGrids;type TfrmConvertDB = class(TForm) btnOK: TButton; Label1: TLabel; db1: TDatabase; {用于连接老数据库系统} db2: TDatabase; {用于连接新数据库系统} dbg: TDBGrid; tblSource: TTable; {dbg的Datasource} qryInsert: TQuery; {用于存放生成的SQL Insert语句} srcSource: TDataSource; tblDest: TTable; {DBGrid1的Datasource} DBGrid1: TDBGrid; srcDest: TDataSource; edFromtbl: TEdit; Label2: TLabel; Label3: TLabel; edToTbl: TEdit; procedure btnOKClick(Sender: TObject); private { Private declarations } public { Public declarations } end;var frmConvertDB: TfrmConvertDB;implementation{$R *.DFM} procedure TfrmConvertDB.btnOKClick (Sender: TObject); var iField :integer; begin if ((edTotbl.text<>'') and (edFromtbl.text<>''))then begin tblSource.TableName:=edFromtbl.text; {指定TableName} tblDest.TableName:=edTotbl.text; with tblSource do begin Open; {打开老系统的表} while EOF=FALSE do begin {逐条记录处理} qryInsert.SQL.Clear; qryInsert.sql.Add ('Insert into '+edTotbl.text + '('); for iField:=0 to dbg.FieldCount-1 do begin qryInsert.sql.add (dbg.Fields[iField].DisplayLabel); if iField<>dbg.FieldCount-1 then qryInsert.sql.add(','); end; qryInsert.sql.add(') values('); for iField:=0 to dbg.FieldCount-1 do begin {进行数据类型转换} if dbg.fields[iField].DataType=ftInteger then qryInsert.sql.add(inttostr (dbg.fields[iField].asInteger)); if dbg.fields[iField].DataType=ftFloat then qryInsert.sql.add(floattostr (dbg.fields[iField].asFloat)); if dbg.fields[iField].DataType=ftDate then qryInsert.sql.add(''''+datetostr (dbg.fields[iField].asDateTime)+''''); if dbg.fields[iField].DataType=ftString then begin if dbg.fields[iField].asString<>'' then qryInsert.sql.add(''''+dbg.fields [iField].asString+'''') else qryInsert.sql.add('NULL'); end; if iField<>dbg.FieldCount-1 then qryInsert.sql.add(','); end; qryInsert.sql.add(')'); qryInsert.ExecSQL; {把数据插入到新系统的表中} next; end; end; tblDest.Close; tblDest.Open;; ShowMessage(' 转换完毕! '); end else ShowMessage ('请输入要插入数据的表的名称 '); end; end.
--/* FoxPro 数据库 select * from openrowset('MSDASQL', 'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\', 'select * from [aa.DBF]') --*//**************导入DBF文件****************/ select * from openrowset('MSDASQL', 'Driver=Microsoft Visual FoxPro Driver; SourceDB=e:\VFP98\data; SourceType=DBF', 'select * from customer where country != "USA" order by country') go /***************** 导出到DBF ***************/ 如果要导出数据到已经生成结构(即现存的)FOXPRO表中,可以直接用下面的SQL语句insert into openrowset('MSDASQL', 'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\', 'select * from [aa.DBF]') select * from 表说明: SourceDB=c:\ 指定foxpro表所在的文件夹 aa.DBF 指定foxpro表的文件名.
to: yq3woaini(哈哈镜(初级代码工)(★★★)) ***************** 导出到DBF ***************/ 如果要导出数据到已经生成结构(即现存的)FOXPRO表中,可以直接用下面的SQL语句insert into openrowset('MSDASQL', 'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\', 'select * from [aa.DBF]') select * from 表1 --------------------------------------- 我试了一下这个语句。出现下述奇怪现象: 如果表1中有数据(不为空)就出错如下: 服务器: 消息 7399,级别 16,状态 1,行 1 OLE DB 提供程序 'MSDASQL' 报错。提供程序报告了意外的灾难性错误。 [OLE/DB provider returned message: 不能更新查询,因为 FROM 子句不是单一的简单表名。] 而如果表1为空的话 就没有问题!!!还请指教!谢谢!
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
StdCtrls, DBTables, Db, Grids, DBGrids;type
TfrmConvertDB = class(TForm)
btnOK: TButton;
Label1: TLabel;
db1: TDatabase; {用于连接老数据库系统}
db2: TDatabase; {用于连接新数据库系统}
dbg: TDBGrid;
tblSource: TTable; {dbg的Datasource}
qryInsert: TQuery;
{用于存放生成的SQL Insert语句}
srcSource: TDataSource;
tblDest: TTable; {DBGrid1的Datasource}
DBGrid1: TDBGrid;
srcDest: TDataSource;
edFromtbl: TEdit;
Label2: TLabel;
Label3: TLabel;
edToTbl: TEdit;
procedure btnOKClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
frmConvertDB: TfrmConvertDB;implementation{$R *.DFM}
procedure TfrmConvertDB.btnOKClick
(Sender: TObject);
var iField :integer;
begin
if ((edTotbl.text<>'') and
(edFromtbl.text<>''))then begin
tblSource.TableName:=edFromtbl.text;
{指定TableName}
tblDest.TableName:=edTotbl.text;
with tblSource do begin
Open; {打开老系统的表}
while EOF=FALSE do begin
{逐条记录处理}
qryInsert.SQL.Clear;
qryInsert.sql.Add
('Insert into '+edTotbl.text + '(');
for iField:=0 to dbg.FieldCount-1 do begin
qryInsert.sql.add
(dbg.Fields[iField].DisplayLabel);
if iField<>dbg.FieldCount-1 then
qryInsert.sql.add(',');
end;
qryInsert.sql.add(') values(');
for iField:=0 to dbg.FieldCount-1 do begin
{进行数据类型转换}
if dbg.fields[iField].DataType=ftInteger then
qryInsert.sql.add(inttostr
(dbg.fields[iField].asInteger));
if dbg.fields[iField].DataType=ftFloat then
qryInsert.sql.add(floattostr
(dbg.fields[iField].asFloat));
if dbg.fields[iField].DataType=ftDate then
qryInsert.sql.add(''''+datetostr
(dbg.fields[iField].asDateTime)+'''');
if dbg.fields[iField].DataType=ftString then begin
if dbg.fields[iField].asString<>'' then
qryInsert.sql.add(''''+dbg.fields
[iField].asString+'''')
else
qryInsert.sql.add('NULL');
end;
if iField<>dbg.FieldCount-1
then qryInsert.sql.add(',');
end;
qryInsert.sql.add(')');
qryInsert.ExecSQL;
{把数据插入到新系统的表中}
next;
end;
end;
tblDest.Close;
tblDest.Open;;
ShowMessage(' 转换完毕! ');
end
else
ShowMessage
('请输入要插入数据的表的名称 ');
end;
end.
select * from openrowset('MSDASQL',
'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\',
'select * from [aa.DBF]')
--*//**************导入DBF文件****************/
select * from openrowset('MSDASQL',
'Driver=Microsoft Visual FoxPro Driver;
SourceDB=e:\VFP98\data;
SourceType=DBF',
'select * from customer where country != "USA" order by country')
go
/***************** 导出到DBF ***************/
如果要导出数据到已经生成结构(即现存的)FOXPRO表中,可以直接用下面的SQL语句insert into openrowset('MSDASQL',
'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\',
'select * from [aa.DBF]')
select * from 表说明:
SourceDB=c:\ 指定foxpro表所在的文件夹
aa.DBF 指定foxpro表的文件名.
***************** 导出到DBF ***************/
如果要导出数据到已经生成结构(即现存的)FOXPRO表中,可以直接用下面的SQL语句insert into openrowset('MSDASQL',
'Driver=Microsoft Visual FoxPro Driver;SourceType=DBF;SourceDB=c:\',
'select * from [aa.DBF]')
select * from 表1
---------------------------------------
我试了一下这个语句。出现下述奇怪现象:
如果表1中有数据(不为空)就出错如下:
服务器: 消息 7399,级别 16,状态 1,行 1
OLE DB 提供程序 'MSDASQL' 报错。提供程序报告了意外的灾难性错误。
[OLE/DB provider returned message: 不能更新查询,因为 FROM 子句不是单一的简单表名。]
而如果表1为空的话 就没有问题!!!还请指教!谢谢!