如何从记录集循环运行多个 DDL 语句?

问题描述 投票:0回答:1

希望这是一个简单的方法 - 出于显而易见的原因,我想重命名数千个字段名称,以删除数百个表中的空格和特殊字符。我将所有编辑内容放入一个简单的表中,并通过查询为每个字段生成 DDL 语句。

如:

currentdb.TableDefs("tblA").Fields("错误字段/名称 - Why_do_this").Name = "GoodFieldName"

我可以在立即窗口中运行DDL语句,没有问题。但是尝试通过循环记录集在 vba 模块中运行它的十几种变体都失败了。

如果我尝试 DoCmd.RunSQL (rs(0)) 并收到错误:

运行时错误‘3129’,无效的SQL语句;应为“DELETE”、“INSERT”、“PROCEDURE”、“SELECT”或“UPDATE”。

(我确实验证了 rs(0) 包含 DDL 文本)。

有没有办法从记录集中运行 DDL 字符串?或者我需要在 VBA 模块内构建该字符串吗?谢谢!!!

ms-access ddl
1个回答
0
投票

您没有提及是否将 SQL DDL“更改表”保存为查询,或者您是否在某个位置存在一些文本文件或 SQL 命令列表?

但是,您当然可以拥有一个 DDL 命令的文本文件,或者一个 DDL 命令表,甚至一堆保存为 DDL 命令的查询。

以上都是可行的选择。

但是,如果我们有一张桌子,这样说:

然后只需构建一个表单 - 继续或其他什么,我们就有了这个:

因此,我们可以为我们想要的每个操作输入命令。请注意,在上面,我们用“;”终止每个命令。

所以,处理上述内容的代码(上面的按钮代码)是这样的:

Private Sub cmdSQL_Click()

    If Me.Dirty Then Me.Dirty = False ' save current reocrd
    
    
    Dim rstSQL      As DAO.Recordset
    
    Dim strSQL      As String
    Dim SQLArray()  As String
    Dim vSQLrun     As Variant
        
    
    Set rstSQL = CurrentDb.OpenRecordset("SELECT * FROM tblSQL ORDER BY ID")
        
    Do While rstSQL.EOF = False
        SQLArray = Split(rstSQL!SQL, ";")
        
        ' Now execute each SQL command in this row
        For Each vSQLrun In SQLArray
           CurrentDb.Execute vSQLrun, dbFailOnError
           'Debug.Print vSQLrun
        Next
    
        rstSQL.MoveNext
    Loop
    
    MsgBox "done"
    
End Sub

请注意,要重命名列,您实际上不能使用 MS-Access DDL 的命令。您必须创建新列、复制数据、删除旧列,并可能添加索引。

如果该列是关系的一部分,那么上述建议并不是真正可行的建议。

但是,对于某些类型的数据库更改,上述方法可能相当有价值。

但是,由于索引和关系的问题(这将与上面的代码破坏),那么我们可以简单地有一个更改表,并且不使用 SQL DDL'命令,而是使用 DAO 对象模型,这将允许我们可以更改列名称,但不必复制或创建新列。

但是,上面确实显示了执行多个命令是多么容易。如前所述,我们还可以从文本文件中逐行读取,并且再次使用与上述类似的方法来“处理”SQL 脚本命令的文本文件。所以,上面是一个SQL脚本运行方案。

MS-access数据引擎无法同时执行多个SQL命令,但如果基于“;”进行分割,那么只需少量的VBA代码即可实现此能力。

在使用 DDL 的命令时,我认为对于添加新列非常有用?

对于重命名,使用 DAO 是更好的选择。

因此,我建议使用包含这些列的表格:

现在,我们再次处理每一行,如下所示:

Sub ChangeColumns()

    Dim rstChanges      As DAO.Recordset
    Dim rtabledef       As DAO.TableDef
    Dim db              As DAO.Database
    
    Set db = CurrentDb
                   
    Set rstChanges = CurrentDb.OpenRecordset("SELECT * FROM tblRenameColumns ORDER BY ID")
            
    Do While rstChanges.EOF = False
    
        Set rtabledef = db.TableDefs(rstChanges!TableName)
        Call MyColRename(rtabledef, rstChanges!OldColumn, rstChanges!NewColumn)
        ' db.TableDefs.Refresh ' optional - do at end of processing
      
        rstChanges.MoveNext
    Loop
    rstChanges.Close
    

End Sub


Sub MyColRename(ByRef rtabledef As DAO.TableDef, sOldCol As String, sNewCol As String)


    Dim fld         As DAO.Field
    
    For Each fld In rtabledef.Fields
        
        If fld.Name = sOldCol Then
            fld.Name = sNewCol
            Exit For
        End If
    Next

End Sub

因此,对于新列,我建议使用第一个示例(使用 SQL DDL 命令)。

但是,使用 DAO 对象模型是重命名现有列的更好选择,如上所示。不需要数据副本,不需要重新索引,事实上,甚至关系也将保持不变。

但是,应用程序中现有的 SQL 命令、现有表单以及 VBA 代码当然都需要更新以反映新的列名称。

© www.soinside.com 2019 - 2024. All rights reserved.