VBA如何将Netezza查询所得Recordset插入Oracle数据库表
核心问题原因
mrecset是VBA内存中归属Netezza连接的记录集对象,Oracle数据库会话无法访问VBA的内存对象,你将字符串"mrecset"拼接进SQL语句后,Oracle会将其识别为本地表名进行查找,自然触发表不存在的报错。
可行实现方案
方案1:小数据量(万条以内)直接遍历插入
实现逻辑最简单,无需额外创建数据库对象,调整后的代码如下:
Sub Netezza_to_Oracle_table() Dim mcon As ADODB.Connection Dim mConnectionString As String Dim mrecset As New ADODB.Recordset Dim mSqlQry As String Dim con As ADODB.Connection Dim ConnectionString As String Dim SqlQry As String Dim i As Long, fieldCount As Long ' 初始化连接 Set mcon = New ADODB.Connection Set mrecset = New ADODB.Recordset Set con = New ADODB.Connection mConnectionString = "dsn=NZSQL;servername=servername;port=1234;database=database;User ID=me01;password=password123" ConnectionString = "GOODSQL.1;User ID=cheese_data;password=password456;Data Source=ORACLE" ' 打开Netezza连接并查询数据 mcon.Open mConnectionString mSqlQry = "SELECT COLUMNS FROM TABLE WHERE ETC " mrecset.Open mSqlQry, mcon, adOpenForwardOnly, adLockReadOnly ' 打开Oracle连接,开启事务提升插入效率 con.Open ConnectionString con.BeginTrans fieldCount = mrecset.Fields.Count ' 遍历Netezza记录集逐行插入Oracle Do While Not mrecset.EOF ' 拼接插入语句,注意字段值的类型转义,字符串类型需要加单引号 SqlQry = "INSERT INTO MY_ORACLE_TABLE VALUES(" For i = 0 To fieldCount - 1 ' 空值处理 If IsNull(mrecset.Fields(i).Value) Then SqlQry = SqlQry & "NULL," Else ' 字符串类型的判断和转义,可根据实际字段类型调整 If VarType(mrecset.Fields(i).Value) = vbString Then SqlQry = SqlQry & "'" & Replace(mrecset.Fields(i).Value, "'", "''") & "'," Else SqlQry = SqlQry & mrecset.Fields(i).Value & "," End If End If Next SqlQry = Left(SqlQry, Len(SqlQry) - 1) & ")" con.Execute SqlQry mrecset.MoveNext Loop ' 提交事务 con.CommitTrans ' 资源释放 mrecset.Close Set mrecset = Nothing mcon.Close Set mcon = Nothing con.Close Set con = Nothing End Sub
方案2:大数据量(10万条以上)临时表方案
你提到的临时表方案是可行的,适合数据量较大的场景,效率远高于逐行插入:
- 首先在Oracle中创建会话级临时表,结构和你要同步的表一致,会话结束后数据会自动清空:
CREATE GLOBAL TEMPORARY TABLE TEMP_MY_TABLE ( -- 和MY_ORACLE_TABLE字段结构完全一致 COL1 VARCHAR2(100), COL2 NUMBER, ... ) ON COMMIT PRESERVE ROWS;
- VBA侧用
UpdateBatch方法将Netezza记录集批量写入临时表,再执行Oracle本地的INSERT INTO MY_ORACLE_TABLE SELECT * FROM TEMP_MY_TABLE完成同步,避免逐行交互的性能损耗。
额外优化建议
如果两个数据库之间网络互通,也可以直接在Oracle中创建Netezza的DBLINK,直接执行INSERT INTO MY_ORACLE_TABLE SELECT * FROM 表名@NZ_DBLINK WHERE 条件,不需要经过VBA中转,性能最高。
内容的提问来源于stack exchange,提问作者Roy Taylor
相关产品推荐
相关产品推荐

