我们有 800 个不同的.dbf
文件,这些文件需要以文件名作为新表名加载到 SQL Server 中,因此file1.dbf
必须加载到 SQL Server 中的表file1
中。
像这样,我们需要将所有 800 个 Foxpro 表加载到 SQL Server 中。有没有人对此有想法或脚本?任何帮助都非常感谢。
这个问题有多种解决方案。一种是使用 VFP 附带的升级向导。我只尝试了原始版本,它一点也不好。从那以后我就没有使用它了。您可以尝试上传一个包含单个表的测试数据库,例如其中有一百万行,只是为了看看使用该表是否可行(一百万行不应超过一分钟)。
我所做的是创建一个"生成器",它将在我想要的映射中创建SQL服务器表(即:备忘录到varchar或varbinary MAX,char到varchar等)。然后使用我编写的基于 C# 的 activex 代码,我加载表 - 一次加载多个表(加载表的其他方法非常慢)。从那时起,该代码用于创建SQL服务器表和/或将现有客户的数据传输到SQL服务器。
另一种有效的方法是,使用 VFPOLEDB 创建一个到 VFP 的链接服务器,然后使用 OpenQuery 获取表的结构和数据:
select * into [TableName]
from OpenQuery(vfpserver, 'select * from TableName ...')
这个也很快,允许您在查询中使用特定于 VFP 的函数,但是生成的字段类型可能不是您想要的。
下面是用 FoxPro 9 编写的解决方案。 您可能需要稍微修改一下,因为我只处理了 3 种数据类型。 您还必须注意 SQL 保留字作为字段名称。
SET SAFETY OFF
CLOSE ALL
CLEAR ALL
CLEAR
SET DIRE TO "C:temp"
** house keeping
RUN del *.fxp
RUN del *.CDX
RUN del *.bak
RUN del *.err
RUN del *.txt
oPrgDir = SYS(5)+SYS(2003) && Program Directory
oPath = "C:temppathtodbfs" && location of dbfs
CREATE TABLE dbfstruct (fldno N(7,0), fldnm c(16), fldtype c(20), fldlen N(5,0), fldpoint N(7,0)) && dbf structure table
STORE SQLSTRINGCONNECT("DRIVER={MySQL ODBC 3.51 Driver};SERVER=localhost;DATABASE=testdbf;UID=root;PWD=root; OPTION=3") TO oConn && SQL connection
SET DIRE TO (m.oPath)
STORE ADIR(aFL, "*.dbf") TO iFL && getting list of dbfs
SET DIRE TO (m.oPrgDir)
FOR i = 1 TO iFL
IF AT("dbfstruct.dbf", LOWER(aFL(i,1))) = 0 THEN
USE oPath + "" + aFL(i,1)
LIST STRUCTURE TO FILE "struct.txt" && output dbf structure to text file"
SET DIRE TO (m.oPrgDir)
USE dbfstruct
ZAP
APPEND FROM "struct.txt" TYPE SDF
DELETE FROM dbfstruct WHERE fldno = 0 && removing non esential text
PACK
CLEAR
DELETE FILE "struct.txt"
SET DIRE TO (m.oPrgDir)
=SQLEXEC(oConn, "DROP TABLE IF EXISTS testdbf." + STRTRAN(LOWER(aFL(i,1)),".dbf", "")) && needed to remove tables already created when I was testing
sSQL = "CREATE TABLE testdbf." + STRTRAN(LOWER(aFL(i,1)),".dbf", "") + " ("
SELECT dbfstruct
GOTO TOP
DO WHILE NOT EOF()
@1,1 SAY "CREATING QUERY: " + aFL(i,1)
sSQL = sSQL + ALLTRIM(LOWER(dbfstruct.fldnm)) + " "
* You may have to add below depending on the field types of your DBFS
DO CASE
CASE ALLTRIM(dbfstruct.fldtype) == "Character"
sSQL = sSQL + "VARCHAR(" + ALLTRIM(STR(dbfstruct.fldlen)) + "),"
CASE ALLTRIM(dbfstruct.fldtype) == "Numeric" AND dbfstruct.fldpoint = 0
sSQL = sSQL + "INT(" + ALLTRIM(STR(dbfstruct.fldlen)) + "),"
CASE ALLTRIM(dbfstruct.fldtype) == "Numeric" AND dbfstruct.fldpoint > 0
sSQL = sSQL + "DECIMAL(" + ALLTRIM(STR(dbfstruct.fldlen)) + "),"
OTHERWISE
=MESSAGEBOX("Unhandled Field Type: " + ALLTRIM(dbfstruct.fldtype) ,0,"ERROR")
CANCEL
ENDCASE
SELECT dbfstruct
SKIP
ENDDO
sSQL = SUBSTR(sSQL, 1, LEN(sSQL)-1) + ")"
STORE SQLEXEC(oConn, sSQL) TO iSQL
IF iSQL < 0 THEN
CLEAR
?sSQL
STORE FCREATE("sqlerror.txt") TO gnOut && SQL of query in case it errors
=FPUTS(gnOut, sSQL)
=FCLOSE(gnOut)
=MESSAGEBOX("Error creating table on MySQL",0,"ERROR")
CANCEL
ENDIF
CLOSE DATABASES
ENDIF
ENDFOR
=SQLDISCONNECT(oConn)
SET DIRE TO (m.oPrgDir)
SET SAFETY ON