在Excel VBA中运行SQL“ SELECT ... INTO ... IN ....”语句

时间:2018-10-03 13:19:40

标签: sql vba excel-vba dao

我似乎找不到任何好的参考资料或示例来说明如何使它工作。我有一个存储在AS / 400上的数据库(我的本地MS Access数据库[存储在网络驱动器上]已使用ODBC / DSN将表链接到400)。我的实用程序可以很好地将SQL语句传递给Access,从而可以使用链接表从400中检索数据。问题在于,对于一​​些较大的报告,以及400处于多个州的事实,运行这些报告可能要花费几个小时。解决此问题的解决方案是仅使用与报告相关的数据集创建所需表的本地“副本”,该数据集是相当小的数据集。显然,这样做不利于不“实时”数据,但我可以接受。最终,我要做的是从链接表中收集相关数据,并将其保存到客户端本地的单独数据库中,以便在异地/脱机时可以使用它,并提高报告的速度。

网络位置存储的数据库= DB1(表链接到AS / 400) 本地客户端存储的数据库= DB2(由下面的SQL创建的相关数据集,非链接表的名称与链接表相同)

下面是我正在尝试使用VBA和DAO进行工作的SQL语句

SELECT 
    DB1_TABLEA.FIELD1, 
    DB1_TABLEA.FIELD2, 
    DB1_TABLEA.FIELD3, 
    DB1_TABLEA.FIELD4, 
    DB1_TABLEA.FIELD5, 
    DB1_TABLEA.FIELD6, 
    DB1_TABLEA.FIELD7, 
    DB1_TABLEA.FIELD8 
INTO 
    DB1_TABLEA IN 'Local_DB_Copy.accdb'    <== Creating non-linked copy 
FROM 
    DB1_TABLEA
WHERE 
    (
        ((DB1_TABLEA.FIELD4) Like 99999) 
        AND 
        ((DB1_TABLEA.FIELD6)="02" Or (DB1_TABLEA.FIELD6)="22")
    )
;

我已经使我的程序运行正常,并从AS / 400 DB返回/处理数据。我只需要能够完成上述工作,以便人们可以选择运行本地副本,因此处理速度会更快。

下面是我尝试过的代码,但是当然失败了,否则我就不在这里。

Sub gCreateLocalDBTables()
    Dim DBPath As String
    Dim LocalDBPath As String
    Dim sSQL As String
    Dim DB As DAO.Database
    Dim DB2 As DAO.Database
    Dim RS As DAO.Recordset
        LocalDBPath = "AS400_Local.accdb"
        sSQL = "SELECT DB1_TABLEA.FIELD1, DB1_TABLEA.FIELD2, DB1_TABLEA.FIELD3, DB1_TABLEA.FIELD4, DB1_TABLEA.FIELD5, DB1_TABLEA.FIELD6, DB1_TABLEA.FIELD7, DB1_TABLEA.FIELD8 INTO DB2_TABLEA IN '" & LocalDBPath & "' FROM DB1_TABLEA WHERE (((DB1_TABLEA.FIELD4) Like 99999) AND ((DB1_TABLEA.FIELD6)='02' Or (DB1_TABLEA.FIELD6)='22'));"
        Set DB = OpenDatabase(LocalDBPath, False, False)
        DB.TableDefs.Delete ("DB2_TABLEA")
        DB.Close
        DBPath = Interaction.GetSetting("Cust_Tools", "Settings\Report_Planning", "400DB_Location")
        Set DB2 = OpenDatabase(DBPath, False, False)
        Set RS = DB2.OpenRecordset(sSQL)
        RS.Close
        DB2.Close
        Set RS = Nothing
        Set DB = Nothing
        Set DB2 = Nothing
End Sub

我知道SQL可以正常工作,因为我已经从MS Access内部进行了测试。我只是找不到有关如何使其从Excel VBA传递的信息

1 个答案:

答案 0 :(得分:1)

您不能为记录集分配动作查询,例如生成表查询(即SELECTINTO调用)。考虑在打开本地表上的记录集之前执行DROPSELECT ... INTO操作查询。同样,还不清楚为什么要打开第二个数据库或该路径指向什么。下面打开有关大型机数据的记录集:

Set DB = OpenDatabase(LocalDBPath, False, False)

DB.Execute "DROP TABLE DB2_TABLEA", dbFailOnError
DB.Execute sSQL, dbFailOnError

Set RS = DB.OpenRecordset("SELECT * FROM DB2_TABLEA")

此外,make table查询中的IN子句是不必要的,因为您当前已连接到要对其执行操作的数据库。只需删除它('“&LocalDBPath&”')。另外,LIKE不带通配符和数字的表达式应替换为=

SELECT 
    DB1_TABLEA.FIELD1, 
    DB1_TABLEA.FIELD2, 
    DB1_TABLEA.FIELD3, 
    DB1_TABLEA.FIELD4, 
    DB1_TABLEA.FIELD5, 
    DB1_TABLEA.FIELD6, 
    DB1_TABLEA.FIELD7, 
    DB1_TABLEA.FIELD8 
INTO 
    DB2_TABLEA 
FROM 
    DB1_TABLEA
WHERE 
    (
        ((DB1_TABLEA.FIELD4) = 99999) 
        AND 
        ((DB1_TABLEA.FIELD6)='02' OR (DB1_TABLEA.FIELD6)='22')
    )
;

实际上,考虑将查询保存在MS Access数据库中(功能区->创建->查询设计-> SQL视图),并将其作为命名对象调用,并避免在VBA中使用任何长的SQL。

DB.Execute "DROP TABLE DB2_TABLEA", dbFailOnError
DB.Execute "mySavedQuery", dbFailOnError

Set RS = DB.OpenRecordset("SELECT * FROM DB2_TABLEA")