无法通过Excel-VBA将SQL代码块执行/传递给Oracle

时间:2019-06-19 07:11:49

标签: excel vba oracle

我正在尝试传递SQL(Oracle)块以获取结果并使用VBA存储在excel中。连接成功建立,并且能够获取简单查询的结果。但是,当用SQL块替换简单查询时,它会返回错误。

注意:由于对数据库的访问受限,因此我无法创建函数。因此,尝试在运行时传递相同的代码块。

尝试实现-从数据库中获取每个表的行数,并通过处理异常将其存储在excel中

cnn_meta.Open (.....)
sqlQry = "DECLARE tmp_table VARCHAR2(125); table_does_not_exist EXCEPTION; PRAGMA EXCEPTION_INIT(table_does_not_exist, -00942); row_cnt integer; " & vbCrLf & _
            "BEGIN FOR cntr IN (SELECT owner,table_name FROM all_tables where owner='APPQOSSYS')" & vbCrLf & _
            "  LOOP BEGIN tmp_table := cntr.owner || '.' || cntr.table_name; EXECUTE IMMEDIATE 'SELECT count(1) FROM ' || tmp_table ||' where rownum =1' into row_cnt; dbms_output.put_line(tmp_table || ' - ' || row_cnt); " & vbCrLf & _
            "        EXCEPTION WHEN table_does_not_exist THEN dbms_output.put_line('table dose not exists - ' || tmp_table); " & vbCrLf & _
            "            WHEN OTHERS THEN IF (SQLCODE = -942) THEN DBMS_Output.Put_Line('in exception'); ELSE DBMS_Output.Put_Line(tmp_table || ' - Dont have access\didnt exist'); END IF; " & vbCrLf & _
            "END; END LOOP; END;"
res_meta.Open sqlQry, cnn_meta, adOpenStatic
For iCols = 0 To res_meta.Fields.Count - 1
            Worksheets("sheet1").Cells(1, iCols + 1).Value = res_meta.Fields(iCols).Name
Next

Worksheets("sheet1").Range("A2").CopyFromRecordset res_meta
res_meta.Close
cnn_meta.Close

当我执行上面的代码时,它返回以下错误

  

运行时错误'3704':
  关闭对象时不允许操作

当我将简单查询替换为上面的代码时,它工作正常。

简单\通过查询-

sqlQry = "select owner,table_name, to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner ||'.'||table_name)),'/ROWSET/ROW/C')) Count " & _
    '         "from all_tables"

1 个答案:

答案 0 :(得分:0)

我相信该错误是由于res_meta.Close

没有记录集返回时,您无法关闭记录集。您的Select...查询确实返回了一个记录集,但快速浏览一下,似乎另一个查询创建了一个临时表,因此没有返回记录集。删除应该关闭记录集的行,然后代码应该起作用。

如果未返回任何记录集,则以下方法将不返回任何内容。

res_meta.Open sqlQry, cnn_meta, adOpenStatic
On Error Resume Next
    Debug.Print rs.EOF
On Error GoTo 0
If err.Number <> 0 Then
    MsgBox "No recordset was returned", vbCritical, "Error"
Else
    For iCols = 0 To res_meta.Fields.Count - 1
        Worksheets("sheet1").Cells(1, iCols + 1).Value = res_meta.Fields(iCols).Name
    Next

    Worksheets("sheet1").Range("A2").CopyFromRecordset res_meta
    res_meta.Close
End If
err.Clear
cnn_meta.Close