Access和ODBC / Oracle都能理解的通用SQL

时间:2017-10-26 19:43:26

标签: sql oracle ms-access odbc query-optimization

我有一个基于链接的ODBC表(Oracle)的MS Access查询。

我在此处对查询效果不佳进行了排查:Access not properly translating TOP predicate to ODBC/Oracle SQL

SELECT ri.*
FROM user1_road_insp AS ri
WHERE ri.insp_id = (
                    select 
                        top 1 ri2.insp_id   
                    from 
                        user1_road_insp ri2 
                    where 
                        ri2.road_id = ri.road_id 
                        and year(insp_date) between  [Enter a START year:] and [Enter a END year:]
                    order by 
                        ri2.insp_date desc, 
                        ri2.length desc,
                        ri2.insp_id
                   );

文档说:

  

当您发现问题时,可以尝试通过更改本地查询来解决问题。这通常很难成功,但你可以   能够添加发送到服务器的条件,减少   为本地处理检索的行数。       在许多情况下,您会发现,尽管您尽了最大的努力,Office Access仍然会不必要地检索整个表   在本地执行最终查询处理。

但是,我发现我并不真正理解我应该编写什么样的SQL来使Access和ODBC / Oracle都满意。

我是否应该编写某种 通用SQL ,Access可以在本地查询中理解 AND ,可以轻松转换为ODBC / Oracle SQL?通用SQL是真的吗?

2 个答案:

答案 0 :(得分:4)

ODBC驱动程序使用什么类型的SQL?它通常依赖于MS Access,它有三种类型的外部数据连接,它们使用不同的SQL方言与ODBC API进行交互。

  1. 链接表,其作用类似于本地表,但是是ODBC连接的数据源,不存储在本地。一旦将它们合并到Access应用程序中,这些表格只能使用MS Access' SQL方言。它们可以与其他来源的本地或其他后端表连接。

    因此,为什么TOP在MS Access中可用而不在Oracle中。您实际上是使用Access SQL来操作Oracle数据。 ODBC作为数据的起点,而Access' Jet / ACE SQL引擎在缓存的内存中进行处理和结果集查看。

    Linked Tables Ribbon Icon

  2. 传递查询,在本地应用的环境中看不到本地表或其他任何内容。此类查询使用连接数据库的SQL方言,这里是Oracle。

    因此,为什么TOP在Oracle中不可用,并且列标识符中允许使用双引号。这种引用在MS Access中会失败。实质上,您使用Oracle SQL来操作Access应用程序中的Oracle数据。您可以获取 sqlout.txt 日志的输出,并在ODBC连接到Oracle数据库的传递查询中运行它。

    Pass Through Query Ribbon Icon

  3. 完全通过VBA等代码运行的
  4. ADO / DAO记录集,是与数据源的直接连接,并使用连接数据库的方言。

    在这里,您使用Oracle SQL通过ODBC API操作Access应用程序中的Oracle数据。

    ADO VBA Reference

  5. 在每种类型中,您都必须连接到后端ODBC数据源。您甚至不需要使用GUI但可以使用Access'用于创建链接表的对象库(请参阅DoCmd.TransferDatabase)并通过querydef(请参阅QueryDef.Connect.Execute)。

    我怀疑你看到的 sqlout.txt 日志是ODBC调用到其原生方言的翻译。

答案 1 :(得分:1)

建立@ Parfait的#1点

来自Mary Chipman和Andy Baron的 Microsoft Access Developer's Guide to SQL Server

优化访问查询:

一种常见的误解是Jet引擎始终检索链接 SQL Server 中的所有数据,然后在本地处理数据。这通常不正确。 Jet完全能够通过ODBC向SQL Server发送高效查询,并仅检索所需的行。但是,在某些情况下,Jet实际上会被迫首先获取某些表中的所有数据然后进行处理。您应该知道何时强制Jet执行此操作并确保它是合理的。以下是创建Access查询时要遵循的一些一般准则:

  • 使用服务器无法评估的表达式将导致Jet检索在本地评估这些表达式所需的所有数据。使用特定于Access的表达式(如域聚合函数,Access财务函数或自定义VBA函数)的影响将根据查询中表达式的使用位置而有所不同。在SELECT子句中使用这样的表达式通常不会导致问题,因为不会返回额外的数据。但是,如果表达式在WHERE子句中,则该标准不能应用于服务器,并且必须返回表达式计算的所有数据。

  • 使用多个条件,将在服务器上处理尽可能多的条件。这意味着即使您使用您知道的标准包括需要由Jet处理的函数,添加可由服务器处理的其他条件也会减少Jet必须处理的记录数。在索引列上添加条件特别有用。

  • 查询包含特定于Access的SQL扩展的语法(ODBC驱动程序不支持)可能会强制通过Access在客户端上完成处理。例如,即使SQL Server现在支持SELECT TOP 5 PERCENT,ODBC驱动程序也不支持它。如果您在Access查询中使用该语法,Jet将需要检索所有记录并计算哪些记录在前5%。另一方面,即使交叉表查询特定于Access,Jet也会翻译除非使用有问题的标准,否则将它们转换为简单的GROUP BY查询并在一次访问服务器时仅获取所需数据。

  • 在检索源数据之后,本地和远程表之间或不同数据源中的远程表之间的异构连接当然必须由Jet处理。但是,如果对远程连接字段建立索引并且表很大,Jet通常会使用索引通过多次调用远程表来检索所需的行,每个行都需要一行。

  • Jet允许您在UNION查询和表达式中的[错误 - 稍后修复]中混合数据类型,但SQL服务器没有。这种数据类型的混合将迫使处理在本地完成。

  • 一个查询中的多个外部联接将在本地处理。

  • 最重要的因素是减少提取的记录总数。 Jet将在后台检索多批记录,直到结果集完成,因此即使您似乎立即得到结果,也会在服务器上为大型结果集继续加载。

注意:这本书已经很老了(2000年出版)并且引用了Jet Engine。我想在使用ACE的较新版本的Access中可能会略有不同,尽管我没有来源支持这一点。