使用 vba 代码更新访问后端架构
Update access backend schema with vba code
我使用 vba 代码在 MS Access 中创建了一个应用程序。该应用程序分为前端和后端。后端保存用户数据。现在我想添加一些新功能,但这需要在架构结构中进行一些过度的后端更改。
我的问题是,每次升级我的应用程序时向最终用户提供我想要的更改的最佳方式或做法是什么?当然,它必须是保持当前数据完整的东西。
我看到了一些关于名为 CompareEm 的免费程序的建议,该程序比较新旧数据库,并生成适当的 vba 代码来完成这项工作。
我也在考虑是否可以更方便地复制一个空数据库,该数据库具有所需的架构以及已升级的前端,并有一个模块将用户的旧数据库与空数据库进行比较,并尝试更改根据新模式的旧模式。 (首先我删除所有关系,转换表,然后重新应用新关系)。
在任何情况下,我都想要一些可以自动完成或通过某些客户代码完成的事情,以避免弄乱用户数据。
感谢任何帮助。
欢迎来到 Stack Overflow!当您发送前端数据库的新版本时,您需要 (1) 包含一个脚本来更新后端数据库,或者 (2) 后端数据库的新副本和一个脚本来传输以前版本的数据。在任何一种情况下,您都需要考虑可能跳过更新的客户,因此您需要在后端数据库上添加某种版本标记。
您可以使用 Access DDL 完成任一策略(参见此处:https://docs.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/data-definition-language) and/or Access DAO (see here: https://docs.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/microsoft-data-access-objects-reference)。
如果您有任何具体问题,请告诉我们,但请记住,SO 并非旨在提供一般性建议或产品评论。
这是 Access 的一个弱点。我们没有真正优秀的脚本语言和系统构建来允许从数据库“模式”中编写脚本。
因此,虽然拆分设计是必须的,并且使代码和应用程序部分的更新变得非常容易,但后端 (BE) 的更新是一个挑战。
我过去曾经这样做过。你是怎么做到的?
那你得定个规矩,规矩是这样的:
任何时候你添加一个新的 field/column,一个新的 table?
您必须将更改写入代码模块。换句话说,您永远不会再使用 GUI 添加新列(或者说更改长度)。您编码到将为您执行此操作的那个子。事实上,在我的一个应用程序中(很多客户,所有 100% 访问 运行 时间)。
那么,添加新功能、更改、修复?我经常不得不添加一些新列或 tables。所以我要做的是将代码写入该“change/update”例程。 (我也给它传递了一个版本号)。在启动时,将调用该代码。
它从大约 5 行代码开始。几年后?我认为它有超过 100 行代码。并且工作得很好。如果他们打开一个较旧的数据文件(BE),那么如果它真的是一个较旧的版本 - 或者说他们没有为升级付费,那么他们当前的软件版本可能并且将会落后几次升级。但是,如前所述,由于在启动时对数据库的所有“更新”总是写成代码,所以即使他们说是 5 个版本,那么所有版本编号的代码都会 运行,进行更改到 BE,他们将是最新的。
因此,这意味着您必须将其编码出来。没那么难,但你确实采用了这种工作方式。
因此,该模块中的代码如下所示:
有两种常见情况。第一个案例是一个全新的 table。我不想写出代码来创建 table,所以我要做的是为此目的在 FE 中包含整个新的 table(我会将字母“C”附加到table).
所以,启动时的代码会检查table是否存在,如果不存在,那么我会执行一个传输命令来复制table。代码存根如下所示:
' 检查新的 table tblRemindDefaults
出错时转到 reminddefaultsadd
设置 rst = CurrentDb.OpenRecordset("tblRemindDefaults")
因此,在上面,我设置了错误处理程序并尝试打开 table。如果 table 不存在,则上面调用例程 remindDefaultsAdd。它的工作当然是将这个新的 table 添加到 BE.
上面的代码存根如下所示:
remindadd:
Dim strFromDB As String
Dim strToDB As String
Dim strSql As String
Dim cp As Object
Dim shellpath As String
strFromDB = CurrentProject.FullName
strToDB = strBackEnd
DoCmd.TransferDatabase acExport, "Microsoft Access", strToDB, acTable, "tblGroupRemindC", "tblGroupRemind", True
请注意我是如何简单地将 table 从 FE 复制到 BE。
下一类升级是向现有 table 添加新列。
同样,与上面类似,代码将检查该列,如果不存在,我将添加该列。在这种情况下,我们没有创建新的 table,因此没有 table.
的副本
典型代码如下所示:
' add our new default user field
Dim nF As dao.field
Dim nT As dao.TableDef
Dim nR As dao.Relation
strFromDB = CurrentProject.FullName
strToDB = strBackEnd
Set db = OpenDatabase(strToDB)
Set nT = db.TableDefs("tblEmployee")
nT.Fields.Append nT.CreateField("DefaultUser", dbText, 25)
nT.Fields.Refresh
Set nT = Nothing
所以在上面我们添加了一个名为 DefaultUser 的新字段到 table。
如果您直接打开 BE,并且不使用链接的 table,那么您可以自由地使用代码修改有问题的 table。您还可以使用 SQL ddl 的语句。因此,虽然我注意到 Access 中的脚本支持并不是那么好,但您可以这样做:
Set db = OpenDatabase(strToDB)
strSql = "ALTER TABLE tblEmployee ADD COLUMN DefaultUser varCHAR(25);"
CurrentDB.Execute strSQL, dbFailOnError.
因此,您可以使用 table defs 编写代码,创建字段并添加它。或者您可以使用 SQL DDL 的语句并执行它们。当然我写的每个升级部分都有版本号测试。
所以,简单的概念就是每次你需要一个新的列,新的 table 等等?
您写出此代码以进行更改。因此,您可能会说工作一两个月会添加一大堆新功能——其中一些功能将需要新的专栏。所以你永远不要使用 GUI 来做这件事。您在升级模块中编写少量代码例程,然后 运行 它们。然后继续发展。因此,当您完成后,对 table(s) 的所有更新现在都已完成,您可以将新的 FE 部署到这些用户。启动时,更新代码将根据版本号 运行。 (我在FE里有一小排table有版本号,在BE里也有一小排table有版本号)。升级后,新的列,新的 tables 现在在 BE 中,然后我当然会更新那个版本号。
因此,您可以组合使用 SQL ddl 命令,或者像我上面那样使用代码创建字段定义。
唯一真正重要的问题是无法对链接的 table 进行 table 更改。所以你必须像我上面那样创建+打开数据库对象的一个单独实例。在启动时,您必须确保没有绑定到链接 table 的主窗体已经或正在 运行ning。 (因为这将打开 BE,并且您不能对打开的 table 进行 table 更改)。
因此,进行更新并不难。但困难的部分是你的自律。您必须始终转到升级例程并在代码中添加新列。这样,在工作几周后,您已经编写出 table 更改,因此能够针对现场较旧的现有 BE 重新编写运行 该代码。
我使用 vba 代码在 MS Access 中创建了一个应用程序。该应用程序分为前端和后端。后端保存用户数据。现在我想添加一些新功能,但这需要在架构结构中进行一些过度的后端更改。
我的问题是,每次升级我的应用程序时向最终用户提供我想要的更改的最佳方式或做法是什么?当然,它必须是保持当前数据完整的东西。
我看到了一些关于名为 CompareEm 的免费程序的建议,该程序比较新旧数据库,并生成适当的 vba 代码来完成这项工作。
我也在考虑是否可以更方便地复制一个空数据库,该数据库具有所需的架构以及已升级的前端,并有一个模块将用户的旧数据库与空数据库进行比较,并尝试更改根据新模式的旧模式。 (首先我删除所有关系,转换表,然后重新应用新关系)。
在任何情况下,我都想要一些可以自动完成或通过某些客户代码完成的事情,以避免弄乱用户数据。
感谢任何帮助。
欢迎来到 Stack Overflow!当您发送前端数据库的新版本时,您需要 (1) 包含一个脚本来更新后端数据库,或者 (2) 后端数据库的新副本和一个脚本来传输以前版本的数据。在任何一种情况下,您都需要考虑可能跳过更新的客户,因此您需要在后端数据库上添加某种版本标记。
您可以使用 Access DDL 完成任一策略(参见此处:https://docs.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/data-definition-language) and/or Access DAO (see here: https://docs.microsoft.com/en-us/office/client-developer/access/desktop-database-reference/microsoft-data-access-objects-reference)。
如果您有任何具体问题,请告诉我们,但请记住,SO 并非旨在提供一般性建议或产品评论。
这是 Access 的一个弱点。我们没有真正优秀的脚本语言和系统构建来允许从数据库“模式”中编写脚本。
因此,虽然拆分设计是必须的,并且使代码和应用程序部分的更新变得非常容易,但后端 (BE) 的更新是一个挑战。
我过去曾经这样做过。你是怎么做到的?
那你得定个规矩,规矩是这样的:
任何时候你添加一个新的 field/column,一个新的 table?
您必须将更改写入代码模块。换句话说,您永远不会再使用 GUI 添加新列(或者说更改长度)。您编码到将为您执行此操作的那个子。事实上,在我的一个应用程序中(很多客户,所有 100% 访问 运行 时间)。
那么,添加新功能、更改、修复?我经常不得不添加一些新列或 tables。所以我要做的是将代码写入该“change/update”例程。 (我也给它传递了一个版本号)。在启动时,将调用该代码。
它从大约 5 行代码开始。几年后?我认为它有超过 100 行代码。并且工作得很好。如果他们打开一个较旧的数据文件(BE),那么如果它真的是一个较旧的版本 - 或者说他们没有为升级付费,那么他们当前的软件版本可能并且将会落后几次升级。但是,如前所述,由于在启动时对数据库的所有“更新”总是写成代码,所以即使他们说是 5 个版本,那么所有版本编号的代码都会 运行,进行更改到 BE,他们将是最新的。
因此,这意味着您必须将其编码出来。没那么难,但你确实采用了这种工作方式。
因此,该模块中的代码如下所示:
有两种常见情况。第一个案例是一个全新的 table。我不想写出代码来创建 table,所以我要做的是为此目的在 FE 中包含整个新的 table(我会将字母“C”附加到table).
所以,启动时的代码会检查table是否存在,如果不存在,那么我会执行一个传输命令来复制table。代码存根如下所示:
' 检查新的 table tblRemindDefaults
出错时转到 reminddefaultsadd 设置 rst = CurrentDb.OpenRecordset("tblRemindDefaults")
因此,在上面,我设置了错误处理程序并尝试打开 table。如果 table 不存在,则上面调用例程 remindDefaultsAdd。它的工作当然是将这个新的 table 添加到 BE.
上面的代码存根如下所示:
remindadd:
Dim strFromDB As String
Dim strToDB As String
Dim strSql As String
Dim cp As Object
Dim shellpath As String
strFromDB = CurrentProject.FullName
strToDB = strBackEnd
DoCmd.TransferDatabase acExport, "Microsoft Access", strToDB, acTable, "tblGroupRemindC", "tblGroupRemind", True
请注意我是如何简单地将 table 从 FE 复制到 BE。
下一类升级是向现有 table 添加新列。
同样,与上面类似,代码将检查该列,如果不存在,我将添加该列。在这种情况下,我们没有创建新的 table,因此没有 table.
的副本典型代码如下所示:
' add our new default user field
Dim nF As dao.field
Dim nT As dao.TableDef
Dim nR As dao.Relation
strFromDB = CurrentProject.FullName
strToDB = strBackEnd
Set db = OpenDatabase(strToDB)
Set nT = db.TableDefs("tblEmployee")
nT.Fields.Append nT.CreateField("DefaultUser", dbText, 25)
nT.Fields.Refresh
Set nT = Nothing
所以在上面我们添加了一个名为 DefaultUser 的新字段到 table。
如果您直接打开 BE,并且不使用链接的 table,那么您可以自由地使用代码修改有问题的 table。您还可以使用 SQL ddl 的语句。因此,虽然我注意到 Access 中的脚本支持并不是那么好,但您可以这样做:
Set db = OpenDatabase(strToDB)
strSql = "ALTER TABLE tblEmployee ADD COLUMN DefaultUser varCHAR(25);"
CurrentDB.Execute strSQL, dbFailOnError.
因此,您可以使用 table defs 编写代码,创建字段并添加它。或者您可以使用 SQL DDL 的语句并执行它们。当然我写的每个升级部分都有版本号测试。
所以,简单的概念就是每次你需要一个新的列,新的 table 等等?
您写出此代码以进行更改。因此,您可能会说工作一两个月会添加一大堆新功能——其中一些功能将需要新的专栏。所以你永远不要使用 GUI 来做这件事。您在升级模块中编写少量代码例程,然后 运行 它们。然后继续发展。因此,当您完成后,对 table(s) 的所有更新现在都已完成,您可以将新的 FE 部署到这些用户。启动时,更新代码将根据版本号 运行。 (我在FE里有一小排table有版本号,在BE里也有一小排table有版本号)。升级后,新的列,新的 tables 现在在 BE 中,然后我当然会更新那个版本号。
因此,您可以组合使用 SQL ddl 命令,或者像我上面那样使用代码创建字段定义。
唯一真正重要的问题是无法对链接的 table 进行 table 更改。所以你必须像我上面那样创建+打开数据库对象的一个单独实例。在启动时,您必须确保没有绑定到链接 table 的主窗体已经或正在 运行ning。 (因为这将打开 BE,并且您不能对打开的 table 进行 table 更改)。
因此,进行更新并不难。但困难的部分是你的自律。您必须始终转到升级例程并在代码中添加新列。这样,在工作几周后,您已经编写出 table 更改,因此能够针对现场较旧的现有 BE 重新编写运行 该代码。