在MS Access中pipe理和debuggingSQL查询

MS Accesspipe理原始SQL查询的能力有限:编辑器非常糟糕,没有语法突出显示,它将原始SQL重新格式化为一个长string,并且不能插入注释。

debugging复杂的SQL查询也是一件痛苦的事情:要么将其分割成许多较小的查询,在模式更改时变得难以pipe理,要么最终导致一个巨大的查询,这个查询是debugging和更新的恶梦。

如何在MS Access中pipe理复杂的SQL查询,以及如何debugging它们?

编辑
目前,我主要是使用记事本+ + +一些语法着色和SQL漂亮打印机合理重新格式化来自Access的原始SQL。
使用外部存储库是有用的,但始终存在两个版本不同步的风险,并且在尝试Access中的查询之前,仍然需要删除注释。

为了进行debugging,我在一个单独的文本编辑器中编辑它们,让我可以合理地格式化它们。 当我发现我需要进行更改时,我在文本编辑器中编辑版本,并将其粘贴回Access,从不在Access中编辑版本。

仍然是一个主要的皮塔饼。

我有几个特定于VBA中的SQL的提示。

把你的SQL代码与一个stringvariables。 我曾经这样做过:

DoCmd.RunSQL "SELECT ..." 

这很难pipe理。 做这个,而不是:

 strSQL = "SELECT ..." DoCmd.RunSQL strSQL 

通常你不能修复查询,除非你看到正在运行的东西。 为此,在执行之前将SQL转储到立即窗口:

 strSQL = "SELECT ..." Debug.Print strSQL Stop DoCmd.RunSQL strSQL 

将结果粘贴到Access的标准查询生成器(您必须使用SQL视图 )。 现在您可以testing最终版本,包括代码处理的variables。

当你准备一个长查询作为一个string,分解你的代码:

 strSQL = "SELECT wazzle FROM bamsploot" _ & vbCrLf & "WHERE plumsnooker = 0" 

我首先学会了使用vbCrLf当我想美化长消息给用户。 后来我发现它使编码时SQL更易读,并且改进了Debug.Print的输出。 (微小的其他好处:每行末尾都不需要空间,新的行语法就是在这里build立的)。

(注意:您可能会认为这会让您在SQL行的右侧添加注释,准备失望。)

正如在这里的其他地方所说,去文本编辑器是节省时间的。 一些文本编辑器比官方的VBA编辑器提供更好的语法突出显示。 (嘿,StackOverflow更好。)它也是有效的删除访问cruft像多余的表引用和WHERE子句中的圆括号。

严重故障排除工作stream程:

 VBA Debug.Print > (capture query during code operation) query builder > (testing lab to find issues) Notepad++ > (text editor for clean-up and review) query builder > (checking, troubleshooting) VBA 

当然,解决问题通常是减less查询的复杂性,直到你能够找出问题(或者至less使其消失!)。 然后你可以把它build立回你想要的杰作。 因为解决棘手的问题可能需要几个周期,所以您可能会反复使用此工作stream程。

debugging更具挑战性。 如果单个列closures,通常很容易修复。 但是我假设你有更复杂的debugging任务需要执行。

当flummoxed,我通常开始debugging与FROM子句。 我追溯到构成较大查询的所有表和子查询,并确保连接被正确定义。

然后我检查我的WHERE子句。 我在表上以及我已经检查过的子查询或者我已经信任的子查询上运行了很多简单的查询,并且确保当我运行更大的查询时,我得到了我期望的WHERE条件到位。 我同时仔细检查JOIN条件。

我仔细检查我的列定义,以确保我正在检索我真正想看到的内容,特别是如果涉及的公式很复杂。 如果在列定义中有一些像协调子查询那样复杂的东西

然后检查是否正确分组数据,确保没有UNION ALLDISTINCT ”和“ UNION ”不会删除必要的重复项。

我不认为我曾经遇到过这样不能被分解的SQL查询。 我并不总是像这样有条不紊,但是这是一个很好的开始打破真正的冲击的方法。


在编写查询时,我可以推荐一件​​事情: 不要在生产代码中使用SELECT * 以这种方式select所有的列是一个维护的噩梦,当你的基础模式改变时,它会导致很大的问题。 如果您正在编写将来要维护的SQL代码,则应该总是写出每一列。 我为自己节省了很多时间,只是摆脱了我的项目中的“ SELECT * ”。

缺点是这些额外的列不会自动出现在引用“ SELECT * ”查询的查询中。 但是,你应该知道你的查询是如何相互关联的,无论如何,如果你需要额外的列,你可以回去添加它们。


在维护一个代码库方面有一些麻烦,但是如果你有版本控制软件,那么麻烦就更值得了。 我听说过使用Access数据库编写SQL代码版本的方法,但不幸的是,我从来没有使用它们。

我写了Access SQL编辑器 – 一个Microsoft Access插件 – 因为我在Access中编写了很多传递查询和更复杂的SQL。 这个加载项的优点是能够在Access应用程序本身中存储格式化的SQL(带注释!)。 将查询复制到新的Access应用程序时,格式将保留。 当内置的编辑器破坏你的格式时,该工具将显示你的原始查询,并通知你的差异。

它目前不debugging; 如果有足够的兴趣,我会追求这一点 – 但是目前这个function集是故意保持小的。

目前不是免费的,但购买许可证非常便宜。 如果你负担不起,你可以联系我 。 这里有一个免费的14天试用版。

安装完成后,可以通过“加载项”菜单访问它(在Access 2010中,它是“数据库工具” – >“添加”)。

如果您在MS Access中执行真正复杂的查询,我会考虑将这些查询的资源库保存在Access数据库本身以外的某个位置…例如,在一个.sql文件中,您可以使用像Intype这样的编辑器进行编辑将提供语法高亮显示。 它会要求你在这两个地方更新查询,但是你最终可能会发现它有一个正式的“正式”位置,它被格式化和正确地突出显示。

或者,如果可能的话,切换到SQL Server 2005 Express Edition,它也是免费的,将通过SQL Management Studio(也是免费的)为您提供所需的function。

recursion类似我使用外部编辑器来编写我的查询。 我使用记事本++的Light Explorer扩展来一次维护几个脚本,记事本2是一次性的脚本。 (我对于Scintilla的编辑有些偏袒。)

另一种select是使用SQL Server Express附带的免费SQL Server Management Studio Express。 (编辑:对不起, EdgarVerona ,我没有注意到你已经提到这一点!)我通常使用它来编写SQL查询,而不是使用Access,因为我通常使用ODBC链接到SQL Server后端。 请注意,Access MDB使用的SQL Server和Jet SQL使用的T-SQL的语法差异有时很大。

你在说什么MS-Access调用“查询”和SQL调用“视图”或关于SQL查询的“MS-Access传递”查询? 有人可能很容易丢失! 我的解决scheme如下

  1. 免费的SQL Server Management Studio Express,我将在这里详细说明和testing我的查询
  2. 客户端的一个查询表,其查询名称( id_Query )的一个字段和查询本身的另一个字段( queryText ,备忘录types)。

然后,当我需要执行一个查询(或者返回一个logging集)时,我的VBA代码中会有一个小函数getSQLQuery

 Dim myQuery as string, _ rsADO as ADODB.recorset rsADO = new ADODB.recordset myQuery = getSQLQuery(myId_Query) 'if my query retunrs a recordset' set rsADO = myADOConnection.Execute myQuery 'or, if no recordset is to be returned' myADOConnection.Execute myQuery 

对于视图,甚至可以将它们保留在服务器端,并从客户端引用它们

 set rsADO = myADOConnection.execute "dbo.myViewName" 

从Smandoli的这个build议扩展到:

 NO: DoCmd.RunSQL ("SELECT ...") YES: strSQL = "SELECT ..." DoCmd.RunSQL (strSQL) 

如果你想把SQL代码保存在一个外部文件中,用你最喜欢的文本编辑器进行编辑(使用语法着色等等),你可以做这样的伪代码:

 // On initialization: global strSQL f = open("strSQL.sql") strSQL = read_all(f) close(f) // To to the select: DoCmd.RunSQL(strSQL) 

这可能有点笨重 – 也许很笨重 – 但它避免了编辑 – 复制粘贴的一致性问题。

显然,这并不直接解决debuggingSQL,但以可读的方式pipe理代码是问题的一部分。

我想我不写复杂的SQL,因为大部分时间我都没有Access SQL编辑器的问题。 这是因为,大多数情况下,我使用QBE来编写SQL,只能插入到SQL视图中去处理QBE不支持的事情(例如非Equi连接,某些子查询forms,UNION等)。 这并不是说我没有任何很难处理的SQL,但是这主要是因为它很隐蔽,而且这是我的错,而不是Access的错。 我有一个可怕的,令人震惊的QueryDef在自1997年以来一直在生产的应用程序,其SQL有11,934个字符。 而且,是的,排除故障是很糟糕的。 几乎所有的编辑都会破坏一些东西。 但那是因为它是坏的SQL。

为什么有人会想把自己写的SQL作为一般规则,我不能说。 除了最微不足道的SQL以外,在我看来,这似乎更麻烦。

这种事情在我看来就像另一个人抵制默认的Access服务的方式。 几乎总是这样,在其他编程环境中经验丰富的用户会急于尝试Access的默认方式。 最终的结果通常是不高兴的每个人。