除了制作850+ UPDATE语句之外还有其他方法吗?

时间:2016-10-10 08:34:11

标签: excel oracle vba excel-vba oracle11g

我正在Excel VBA中制作一些东西,我需要从Excel工作表中读取大约850行或更多行,并在oracle 11g的现有表中更新它们。幸运的是,我只感兴趣的是两列。

我目前正在做的唯一方法就是在Excel中循环使用Range,并为数组中的每个字段创建一个UPDATE myTable SET Temp = Array(i, 2) WHERE id = Array(i,1)

现在......我非常清楚这不是快速的,也不是优雅的,这就是为什么我正在寻找优化这种东西的技巧和窍门。

我非常感谢所提供的每一个提示。

=== UPDATE ===

通过制作临时表来测试Kacpers建议后,结果是当使用我感兴趣的2列(大约850行)的excel时,大约需要2分钟读取数据并使用{{{{{{{ 1}}方法,850插入。
另一个表和excel文件有大约970行和3列,而过滤掉我写了大约700行,stll使用大约一分钟完成。

最后一部分是与现有表结合,而此实现之前的过程大约需要35秒,现在需要45-55秒。

这似乎仍然是一种非常缓慢的方法。特别是插入部分 就像我在评论中所说的那样,我无法访问服务器存储系统,因此无法上传或制作CSV来导入数据。

仍然非常感谢我可以用来优化程序的任何提示或提示。

3 个答案:

答案 0 :(得分:1)

首先请将您的Excel导入到表或根据xls文件中的csv数据创建外部表。假设您使用列c1,c2

将数据导入到表t1

然后你可以执行合并操作:

merge into myTable mt
using t1
on (mt.id = t1.c1)
when matched then update set
Temp = c2;

如果你需要插入myTable中不存在的行,你可以另外放when not matched then insert;

答案 1 :(得分:1)

您应该使用带有绑定变量的预处理语句(未经测试):

Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = con ' your "ADODB.Connection" object
cmd.CommandType = adCmdText
cmd.CommandText = "UPDATE myTable SET Temp = ? WHERE id = ?"    
cmd.Parameters.Append cmd.CreateParameter("newVal", adVarChar, adParamInput, 10)
cmd.Parameters.Append cmd.CreateParameter("id", adBigInt, adParamInput)

con.BeginTrans
For i = 1 To 850
   cmd.Parameters("newVal").Value = Array(i, 2)
   cmd.Parameters("id").Value = Array(i, 1)
   cmd.Execute
Next
con.CommitTrans

重要提示:cmd.Parameters.Append必须在循环外只进行一次。否则你将无法获得任何收益。

很可能它不会像Direct-Path INSERT那样快(例如外部表),但性能应该足够。

答案 2 :(得分:0)

好的,所以我使用了Kacper建议的一半解决方案,这意味着我引入了一个临时表,我首先使用~850 INSERT填充了以下内容: INSERT ALL INSERT ... END但解决方案需要大约1-2分钟才能执行。

另一个主题建议我"连接"将我的数据转换为单个插入命令并仅执行一次 这似乎是最有效的方法,所以我的插入目前看起来像:

INSERT INTO myTempTable (id, temp) SELECT 'data1', 'data2' from dual
UNION ALL SELECT 'data3', 'data4' from dual
UNION ALL SELECT 'data5', 'data6' from dual
...

仅花费大约一秒时间执行所有850次插入,并通过平均加入仅约5秒来延长myTable的更新。

感谢大家参与,并提供了您提供的有用提示!