Sql server MS Access前端与SQL Server后端查询存储最佳实践
我正在尝试更好地优化我的项目组织。使用MS Access作为前端,SQL Server作为后端,我的目标是尽可能多地分离,遵循最佳实践,并能够使用不同/多个前端(web、c#、python)。为了实现我的目标,我决定遵循一些设计决策:Sql server MS Access前端与SQL Server后端查询存储最佳实践,sql-server,ms-access,view,parameters,common-table-expression,Sql Server,Ms Access,View,Parameters,Common Table Expression,我正在尝试更好地优化我的项目组织。使用MS Access作为前端,SQL Server作为后端,我的目标是尽可能多地分离,遵循最佳实践,并能够使用不同/多个前端(web、c#、python)。为了实现我的目标,我决定遵循一些设计决策: 尽可能使用视图在后端存储尽可能多的复杂查询 尽可能多地使用存储过程在后端进行处理 退出使用链接表,切换到使用简短查询在VBA代码中生成记录集 在玩SQL Server的一些流行功能时,我发现了自己无法解决的问题 CTE可以参数化。视图不能。那么存储在视图中的
- 尽可能使用视图在后端存储尽可能多的复杂查询
- 尽可能多地使用存储过程在后端进行处理
- 退出使用链接表,切换到使用简短查询在VBA代码中生成记录集
- CTE可以参数化。视图不能。那么存储在视图中的CTE呢?如果答案是否定的,那么是否有其他方便的方法来存储CTE服务器端并从VBA调用它来构建记录集?其他参数化查询呢
- 在MS Access中编写复杂的查询作为VBA代码是一件痛苦的事情。。。手指和眼睛。也许还有其他方法可以像老板一样在Access中存储查询
- 你如何组织你的前端-后端应用程序,尤其是如果frontnend是MS Access,并且打算移动到任何其他平台
烟雾。CTE与是否有参数无关。CTE与在查询(或者现在是视图上的视图)上编写查询的想法完全相同。不必编写(并保存)两个视图?你可以使用CTE 然而,CTE在哪里最有用?尤其是在访问上下文中? Access SQL的一个非常好的特性是,别名列可以在该SQL的表达式中重复使用。使用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 server),我们不能使用别名列。
那么,你现在明白了:
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不允许在表达式中重复使用列(就像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
现在,请注意我们仍然必须重复balance表达式,但至少现在我们可以在进一步的表达式中使用计算列,而不必重复它们。
因此,CTE是一个很好的特性,可以帮助您转换Access SQL中所有令人惊叹的查询,这些查询“非常好地”能够在T-SQL中重复(重用)任何经过序列化的表达式
至于热膨胀系数和参数?它们之间的连接为零。CTE不支持t-sql中的任何东西,也不比t-sql中的任何东西多或少有参数。(所以CTE和我在这里看到的参数之间没有联系)
但是,问题的答案是什么?你能在视野中使用CTE吗?是的,你可以,没有什么理由不这样做。在CTE之前,您可以使用一些技巧,或者(喘息)简单地创建一个视图,保存它,然后在该视图上创建另一个视图。因此,CTE实际上只是一种对查询执行查询的简单方法,无需创建单独的视图进行查询
但是,总而言之,CTE可以用作视图,主要原因是T-SQL缺少Access SQL的可爱功能,它允许在T-SQL没有的情况下重复使用别名列。因此,在尝试将Access SQL转换为T-SQL时,CTE的问题尤其重要—它使您重新获得Access在SQL中所具有的这一奇妙功能,以及T-SQL语法中您将严重错过的一项功能
在MS Access中编写复杂的查询作为VBA代码是一件痛苦的事情
嗯,我不能说.net或其他大多数语言中的代码中的内嵌sql也很干净。您倾向于使用字符串连接,这总是一个挑战,但我不能说在say.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中,典型的做法是)保存该查询,因此上面的代码成为一行代码
例如:
因此,VBA中丑陋的内嵌式sql肯定可以通过保存这些查询而不是将它们写在代码中来“驯服”。如果您使用内嵌式sql,我不能说.net会更好(因为您必须处理连接对象、命令对象,而且在大多数情况下还必须处理数据适配器?那么,.net代码会变得更加冗长,需要比VBA中的一行代码更多的代码来完成同样的事情
好的,这就解决了CTE问题,以及在VBA代码中使用SQL的问题
至于在Access中组织FE?好吧,以最少的工作量获得最好的性能?毫无疑问,视图是一种方式。原因是Access非常好
如果您在Access中有一个表单,请说直接绑定到链接表。在sql server之前,该表单将绑定到accDB后端
假设有一百万行。
假设access后端是文件夹中的共享accDB。
假设表单基于此链接表
那么,在过去,您如何启动+加载并显示一条记录,而只从网络管道中拉出一条记录呢?
嗯,除非通过where子句,否则不会启动表单
您可以这样做:
dim strInvoice as string
strInvoice = InputBox("Enter invoice number")
docmd.OpenForm "frmInvoices",,,"InvoiceNum = " & strInvoice
好吧,现在Access只会从网络管道中拖出一条记录,而不是整个表
现在,假设我们将BE表迁移到SQL server?
现在,假设我们仍然将发票表单链接到该链接
dim strInvoice as string
strInvoice = InputBox("Enter invoice number")
docmd.OpenForm "frmInvoices",,,"InvoiceNum = " & strInvoice
dim strInvoice as string
strInvoice = InputBox("Enter invoice number")
docmd.OpenForm "frmInvoices",,,"InvoiceNum = " & strInvoice
with CurrentDB.queryDefs("ptGetIvnoice")
.SQL = "Exec GetInoice " & strInvoice
rst = .OpenRecordSet
end with