具有 SQL 服务器后端查询存储最佳实践的 MS Access 前端
MS Access frontend with SQL Server backend query storing best practices
我正在尝试更好地优化我的项目组织。使用 MS Access 作为前端,SQL 服务器作为后端,我的目标是尽可能地分离,遵循最佳实践并带来使用不同/多个前端(web、c#、python)的能力。为了实现我的目标,我决定遵循一些设计决策:
- 尽可能多地使用视图在后端存储复杂查询
- 尽可能多地使用存储过程在后端进行处理
- 停止使用链接表并切换到使用简短查询在 VBA 代码中生成记录集。
使用 SQL 服务器的一些流行功能,我发现了我无法自行解决的问题。
- CTE 可以参数化。意见不能。存储在视图中的 CTE 怎么样?如果答案是否定的,那么是否有任何其他方便的方法来存储 CTE 服务器端并从 VBA 调用它来构建记录集?其他参数化查询呢?
- 在 MS Access 中编写复杂的查询作为 VBA 代码是……手指和眼睛的痛苦。也许还有其他方法可以像老板一样在Access中存储查询?
- 您如何组织您的前端-后端应用程序,尤其是当前端是 MS Access 并且打算将其移动到任何其他平台时?
蒂亚
烟.
CTE 有零零与有无参数有关。 CTE 与在查询上编写查询(或现在在视图上编写视图)的想法完全相同。不必编写(并保存)两个视图?您可以使用 CTE。
但是,CTE 在哪些方面最有用?特别是在访问上下文中?
好吧,Access SQL 的一个非常非常好的功能是在 sql 的表达式中别名列可以是 re-used。使用 T-SQL 语法,你不能!。结果非常丑陋 T-SQL.
在 Access 中进行这个典型的查询 (Access SQL) 不错(简单 + 容易)的查询:
SELECT
ID, Company, State,
(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased,
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments,
(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate,
(Purchased - Payments) as Balance,
(Balance * TaxRate) as BalanceWithTax
如你所见?在上面,我们使用子查询来获取购买、付款和税率。然后我们在表达式中使用这 3 个。
但是,对于 T-SQL(sql 服务器),我们不能使用别名列。
所以,你现在明白了:
SELECT ID, Company, State,
(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased,
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments,
(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate,
((SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) -
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id)) as Balance,
( (SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) -
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id)) *
(SELECT TaxRate from TaxRates where State = Customers.State) as BAlanceWithTax
FROM Customers
以上是一个简单的例子。所以在上面,t-sql 不允许 re-use 列在表达式中(就像 Access SQL 那样)。因此,以上,或者说将 Access SQL 转换为 T-SQL 是一种皇家痛苦——简直是彻头彻尾的痛苦。
因此,我们可以使用 t-sql 中的 CTE 来“驯服”上述内容。我们可以去:
WITH MyCTE
AS
(SELECT ID, Company, State,
(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased,
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments,
(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate
FROM Customers)
SELECT ID, Company, State, Purchases, Payments, TaxRate,
(Purchases - Payments) as Balance,
( (Purchases - Payments) * TaxRate) as BalanceWithTax
from mycte
现在,请注意我们仍然必须重复平衡表达式,但至少我们现在可以在更多表达式中使用计算列而不必重复它们。
因此,CTE 是一个很棒的功能,可以帮助您转换 Access SQL 中的所有那些令人惊叹的查询,“非常好”具有重复(re-use)T-SQL 中任何 Alised 表达式的能力。
至于 CTE 和参数?他们彼此之间有零零的联系。与 t-sql 中的任何其他内容相比,CTE 不支持或没有任何参数。 (所以我在这里看到的 CTE 和参数之间没有联系)。
但是,问题的答案呢?您可以在视图中使用 CTE 吗?是的,你可以,而且没有理由不这样做。在 CTE 之前,您可以使用一些技巧,或者(喘气)简单地创建一个视图,保存它,然后在其上创建另一个视图。因此,CTE 实际上只是一种简单的查询查询方式,无需创建单独的视图来查询。
但是,总而言之,CTE 可以用作视图,主要原因是 T-SQL 缺少 Access SQL 的可爱功能,它允许 re-use 的别名列,其中 as T-SQL 没有。因此,在尝试将 Access SQL 转换为 T-SQL 时,CTE 的问题尤为重要 - 它可以让您恢复 Access 在 sql 中具有的这种奇妙功能,以及您会非常想念的功能在 T-SQL 语法中。
Writing complicated queries in MS Access as the VBA code is pain
好吧,我不能说 .net 或大多数其他语言的代码中的 in-line sql 都那么干净。您倾向于使用字符串连接,这始终是一个挑战,但我不能说在 .net 开发中这样做比 VBA 更好。
但是,在大多数情况下?
将 sql 文本作为保存的查询放入 Access 中,然后在您的代码中使用它。
所以,运行 我们上面的例子?
您可以在代码中使用:
dim strSQL as string
strSQL = "SELECT ID, Company, State," & _
"(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased," &
"(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments," & _
"(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate," & _
"(Purchased - Payments) as Balance," & _
"(Balance * TaxRate) as BalanceWithTax " & _
dim rst as DAO.RecordSet
set rst = CurrentDB.OpenRecordSet(strSQL)
真的不能说上面写的比用大多数其他语言写上面写的更糟糕。
但是,当然可以(在 Access VBA 中通常会)保存该查询,因此上面的代码变成一行代码。
例如:
set rst = CurrentDB.OpenRecordSet("qryGetBalance")
因此,VBA 中丑陋的 in-line sql 当然可以通过保存此类查询而不是将其写入代码来“驯服”。我不能说如果你使用 in-line sql .net 会更好(并且因为你必须处理连接对象,命令对象,并且在大多数情况下是数据适配器?好吧,那就是.net 代码变得更加冗长,需要更多的代码然后 VBA 中的一行代码来做同样的事情。
好的,这样就可以解决您的 CTE 问题和 in-line 的问题,并在 VBA 代码中使用 SQL。
关于在Access中组织FE?那么,以最少的工作量获得最佳性能?毫无疑问,观点是必经之路。原因是 Access 玩起来非常好。
如果您在 Access 中有一个表单。说直接绑定到链接 table。在 sql 服务器之前,该表单将绑定到 accDB 后端。
假设有 100 万行。
假设访问后端是文件夹中的共享 accDB。
假设表单基于此链接 table.
那么,过去您是如何启动 + 加载和显示一条记录,并且只从网络管道中拉出一条记录的?
好吧,除非你传递一个 where 子句,否则你不会启动表单。
你这样做:
dim strInvoice as string
strInvoice = InputBox("Enter invoice number")
docmd.OpenForm "frmInvoices",,,"InvoiceNum = " & strInvoice
好吧,现在 Access 只会从网络管道中提取一条记录。不是整个table.
现在,假设我们将 BE table 迁移到 SQL 服务器?
现在,假设我们仍然将发票表格链接到链接的 table 100 万行。
当然,数据现在位于 sql 服务器中。
如何在网络管道中只拉出一排?
你可以使用这个:
dim strInvoice as string
strInvoice = InputBox("Enter invoice number")
docmd.OpenForm "frmInvoices",,,"InvoiceNum = " & strInvoice
(相同的代码)。作为clie访问t 仍然只会拉一排。尽管表单直接基于链接 table,但还是如此。所以,一般来说,access不会拉全table。它没有访问后端 (BE),如果您有链接 table 和直接绑定到 100 万行的链接 table 的表单,它也不会。
关于使用 Access 作为 sql 服务器的 FE,这里并没有太多考虑,而且你在“未来”说要使用 .net 或现在这些天一些基于 Web发展方针。
唯一真正的提示和问题是您实际上不需要或可以大量采用从 Access 到 sql 的参数的使用。但是有了 Access where 子句,那么你很少需要(所以,是的,在 Access 中使用 open form/report 的“where”子句来获得窃取性能,并限制拉到访问客户端的网络数据。所以虽然大多数开发平台都围绕基于 sql 的参数生存和死亡?Access 根本不是这些情况之一。你生存和死亡(使用很多)Access 中 where 子句的概念,因为它与 [=119 配合得很好=] 服务器并通过使用 open form/report.
的 where 子句实现仅将数据拉下您告诉访问 grab/get 的网络管道的目标
哪里可以得到“最”re-use?嗯,是的,对于复杂的 Access(客户端)查询?是的,将它们移到视图中。对于一些变得相当复杂的查询,您可以使用 Access 中的存储过程。 (这意味着 pass-though 查询)。
所以,在访问中,假设我们有一个复杂的发票检索,其中涉及复杂的联接和大量查询?然后你可以创建一个存储过程,然后从访问中使用它来获取数据:
with CurrentDB.queryDefs("ptGetIvnoice")
.SQL = "Exec GetInoice " & strInvoice
rst = .OpenRecordSet
end with
又是4行代码。因此,一个非常好的提示是,您是在 VBA 还是 .net 或其他任何格式中编写代码?没有 in-line 连接字符串代码。正如您在上面看到的那样,在 VBA 中,我们在代码中没有任何连接字符串 - 即使在上面使用 T-SQL 存储过程时也不需要它。
所以,是的,使用视图意味着您的 asp.net 或您最终采用的任何系统允许您使用您保存的相同视图 SQL 服务器端,从而访问,或网络或任何其他软件都可以使用相同的视图。
另一个问题是访问会很好地处理视图,您很少需要在 T-SQL 中采用存储过程来进行基于参数的查询。原因当然是 Access 具有我上面提到的“where”子句。没有 T-SQL 参数,并且向访问中的链接视图添加条件(where 子句)将执行与存储过程相同的操作,但没有 Access 最初不支持的 missay 参数。
因此,视图在 Access 开发中接近顶峰,因为 Access 与它们配合得很好,这也意味着当您采用 asp.net 或其他任何方式时,此类视图可以是 re-used目标最终是 re-place 访问。但是,当您的后端是 sql 服务器时,Access 确实是一个很棒的 RAD 工具。因此,当您这样做时,您可以获得良好的可扩展性、更好的安全性,当然还有 asp.net 甚至其他桌面开发平台使用该数据。通常在将 Access 数据移动到 sql 服务器后,公司会发现几乎不需要放弃访问,因为所有这些表格、报告和代码都可以继续使用,同时采用基于 Web 的技术。
我正在尝试更好地优化我的项目组织。使用 MS Access 作为前端,SQL 服务器作为后端,我的目标是尽可能地分离,遵循最佳实践并带来使用不同/多个前端(web、c#、python)的能力。为了实现我的目标,我决定遵循一些设计决策:
- 尽可能多地使用视图在后端存储复杂查询
- 尽可能多地使用存储过程在后端进行处理
- 停止使用链接表并切换到使用简短查询在 VBA 代码中生成记录集。
使用 SQL 服务器的一些流行功能,我发现了我无法自行解决的问题。
- CTE 可以参数化。意见不能。存储在视图中的 CTE 怎么样?如果答案是否定的,那么是否有任何其他方便的方法来存储 CTE 服务器端并从 VBA 调用它来构建记录集?其他参数化查询呢?
- 在 MS Access 中编写复杂的查询作为 VBA 代码是……手指和眼睛的痛苦。也许还有其他方法可以像老板一样在Access中存储查询?
- 您如何组织您的前端-后端应用程序,尤其是当前端是 MS Access 并且打算将其移动到任何其他平台时?
蒂亚 烟.
CTE 有零零与有无参数有关。 CTE 与在查询上编写查询(或现在在视图上编写视图)的想法完全相同。不必编写(并保存)两个视图?您可以使用 CTE。
但是,CTE 在哪些方面最有用?特别是在访问上下文中? 好吧,Access SQL 的一个非常非常好的功能是在 sql 的表达式中别名列可以是 re-used。使用 T-SQL 语法,你不能!。结果非常丑陋 T-SQL.
在 Access 中进行这个典型的查询 (Access SQL) 不错(简单 + 容易)的查询:
SELECT
ID, Company, State,
(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased,
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments,
(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate,
(Purchased - Payments) as Balance,
(Balance * TaxRate) as BalanceWithTax
如你所见?在上面,我们使用子查询来获取购买、付款和税率。然后我们在表达式中使用这 3 个。 但是,对于 T-SQL(sql 服务器),我们不能使用别名列。 所以,你现在明白了:
SELECT ID, Company, State,
(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased,
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments,
(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate,
((SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) -
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id)) as Balance,
( (SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) -
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id)) *
(SELECT TaxRate from TaxRates where State = Customers.State) as BAlanceWithTax
FROM Customers
以上是一个简单的例子。所以在上面,t-sql 不允许 re-use 列在表达式中(就像 Access SQL 那样)。因此,以上,或者说将 Access SQL 转换为 T-SQL 是一种皇家痛苦——简直是彻头彻尾的痛苦。
因此,我们可以使用 t-sql 中的 CTE 来“驯服”上述内容。我们可以去:
WITH MyCTE
AS
(SELECT ID, Company, State,
(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased,
(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments,
(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate
FROM Customers)
SELECT ID, Company, State, Purchases, Payments, TaxRate,
(Purchases - Payments) as Balance,
( (Purchases - Payments) * TaxRate) as BalanceWithTax
from mycte
现在,请注意我们仍然必须重复平衡表达式,但至少我们现在可以在更多表达式中使用计算列而不必重复它们。 因此,CTE 是一个很棒的功能,可以帮助您转换 Access SQL 中的所有那些令人惊叹的查询,“非常好”具有重复(re-use)T-SQL 中任何 Alised 表达式的能力。
至于 CTE 和参数?他们彼此之间有零零的联系。与 t-sql 中的任何其他内容相比,CTE 不支持或没有任何参数。 (所以我在这里看到的 CTE 和参数之间没有联系)。
但是,问题的答案呢?您可以在视图中使用 CTE 吗?是的,你可以,而且没有理由不这样做。在 CTE 之前,您可以使用一些技巧,或者(喘气)简单地创建一个视图,保存它,然后在其上创建另一个视图。因此,CTE 实际上只是一种简单的查询查询方式,无需创建单独的视图来查询。
但是,总而言之,CTE 可以用作视图,主要原因是 T-SQL 缺少 Access SQL 的可爱功能,它允许 re-use 的别名列,其中 as T-SQL 没有。因此,在尝试将 Access SQL 转换为 T-SQL 时,CTE 的问题尤为重要 - 它可以让您恢复 Access 在 sql 中具有的这种奇妙功能,以及您会非常想念的功能在 T-SQL 语法中。
Writing complicated queries in MS Access as the VBA code is pain
好吧,我不能说 .net 或大多数其他语言的代码中的 in-line sql 都那么干净。您倾向于使用字符串连接,这始终是一个挑战,但我不能说在 .net 开发中这样做比 VBA 更好。 但是,在大多数情况下?
将 sql 文本作为保存的查询放入 Access 中,然后在您的代码中使用它。 所以,运行 我们上面的例子?
您可以在代码中使用:
dim strSQL as string
strSQL = "SELECT ID, Company, State," & _
"(SELECT SUM(Price) FROM Purchases where Customer_ID = Customers.ID) as Purchased," &
"(SELECT SUM(Payment) FROM Payments where Customer_ID = Customers.id) as Payments," & _
"(SELECT TaxRate from TaxRates where State = Customers.State) as TaxRate," & _
"(Purchased - Payments) as Balance," & _
"(Balance * TaxRate) as BalanceWithTax " & _
dim rst as DAO.RecordSet
set rst = CurrentDB.OpenRecordSet(strSQL)
真的不能说上面写的比用大多数其他语言写上面写的更糟糕。 但是,当然可以(在 Access VBA 中通常会)保存该查询,因此上面的代码变成一行代码。
例如:
set rst = CurrentDB.OpenRecordSet("qryGetBalance")
因此,VBA 中丑陋的 in-line sql 当然可以通过保存此类查询而不是将其写入代码来“驯服”。我不能说如果你使用 in-line sql .net 会更好(并且因为你必须处理连接对象,命令对象,并且在大多数情况下是数据适配器?好吧,那就是.net 代码变得更加冗长,需要更多的代码然后 VBA 中的一行代码来做同样的事情。
好的,这样就可以解决您的 CTE 问题和 in-line 的问题,并在 VBA 代码中使用 SQL。
关于在Access中组织FE?那么,以最少的工作量获得最佳性能?毫无疑问,观点是必经之路。原因是 Access 玩起来非常好。
如果您在 Access 中有一个表单。说直接绑定到链接 table。在 sql 服务器之前,该表单将绑定到 accDB 后端。
假设有 100 万行。 假设访问后端是文件夹中的共享 accDB。 假设表单基于此链接 table.
那么,过去您是如何启动 + 加载和显示一条记录,并且只从网络管道中拉出一条记录的? 好吧,除非你传递一个 where 子句,否则你不会启动表单。
你这样做:
dim strInvoice as string
strInvoice = InputBox("Enter invoice number")
docmd.OpenForm "frmInvoices",,,"InvoiceNum = " & strInvoice
好吧,现在 Access 只会从网络管道中提取一条记录。不是整个table.
现在,假设我们将 BE table 迁移到 SQL 服务器? 现在,假设我们仍然将发票表格链接到链接的 table 100 万行。 当然,数据现在位于 sql 服务器中。 如何在网络管道中只拉出一排? 你可以使用这个:
dim strInvoice as string
strInvoice = InputBox("Enter invoice number")
docmd.OpenForm "frmInvoices",,,"InvoiceNum = " & strInvoice
(相同的代码)。作为clie访问t 仍然只会拉一排。尽管表单直接基于链接 table,但还是如此。所以,一般来说,access不会拉全table。它没有访问后端 (BE),如果您有链接 table 和直接绑定到 100 万行的链接 table 的表单,它也不会。
关于使用 Access 作为 sql 服务器的 FE,这里并没有太多考虑,而且你在“未来”说要使用 .net 或现在这些天一些基于 Web发展方针。
唯一真正的提示和问题是您实际上不需要或可以大量采用从 Access 到 sql 的参数的使用。但是有了 Access where 子句,那么你很少需要(所以,是的,在 Access 中使用 open form/report 的“where”子句来获得窃取性能,并限制拉到访问客户端的网络数据。所以虽然大多数开发平台都围绕基于 sql 的参数生存和死亡?Access 根本不是这些情况之一。你生存和死亡(使用很多)Access 中 where 子句的概念,因为它与 [=119 配合得很好=] 服务器并通过使用 open form/report.
的 where 子句实现仅将数据拉下您告诉访问 grab/get 的网络管道的目标哪里可以得到“最”re-use?嗯,是的,对于复杂的 Access(客户端)查询?是的,将它们移到视图中。对于一些变得相当复杂的查询,您可以使用 Access 中的存储过程。 (这意味着 pass-though 查询)。
所以,在访问中,假设我们有一个复杂的发票检索,其中涉及复杂的联接和大量查询?然后你可以创建一个存储过程,然后从访问中使用它来获取数据:
with CurrentDB.queryDefs("ptGetIvnoice")
.SQL = "Exec GetInoice " & strInvoice
rst = .OpenRecordSet
end with
又是4行代码。因此,一个非常好的提示是,您是在 VBA 还是 .net 或其他任何格式中编写代码?没有 in-line 连接字符串代码。正如您在上面看到的那样,在 VBA 中,我们在代码中没有任何连接字符串 - 即使在上面使用 T-SQL 存储过程时也不需要它。
所以,是的,使用视图意味着您的 asp.net 或您最终采用的任何系统允许您使用您保存的相同视图 SQL 服务器端,从而访问,或网络或任何其他软件都可以使用相同的视图。
另一个问题是访问会很好地处理视图,您很少需要在 T-SQL 中采用存储过程来进行基于参数的查询。原因当然是 Access 具有我上面提到的“where”子句。没有 T-SQL 参数,并且向访问中的链接视图添加条件(where 子句)将执行与存储过程相同的操作,但没有 Access 最初不支持的 missay 参数。
因此,视图在 Access 开发中接近顶峰,因为 Access 与它们配合得很好,这也意味着当您采用 asp.net 或其他任何方式时,此类视图可以是 re-used目标最终是 re-place 访问。但是,当您的后端是 sql 服务器时,Access 确实是一个很棒的 RAD 工具。因此,当您这样做时,您可以获得良好的可扩展性、更好的安全性,当然还有 asp.net 甚至其他桌面开发平台使用该数据。通常在将 Access 数据移动到 sql 服务器后,公司会发现几乎不需要放弃访问,因为所有这些表格、报告和代码都可以继续使用,同时采用基于 Web 的技术。