访问QueryDefs错误保存的子查询SQL
Access以一种奇怪的方式存储它的SQL用于子查询:s似乎用方括号“ []”代替括号“()”,并且(通常)添加了多余的“”。 之后。
例如,一个简单的例子说明了它如何
作品 :SELECT subA.*
FROM ( SELECT [fA], [fB]
FROM [MyTable] ) AS subA
成为(在Access中另存为querydef后):
SELECT subA.*
FROM [ SELECT [fA], [fB]
FROM [MyTable] ]. AS subA
我不知道为什么Access会这样做,但这似乎是一致的。
在某些版本中,Access可以识别生成的SQL,但在较早版本中,它无法识别自己的SQL。
从访问QueryDef访问SQL基本上有两种方法。
- 设计QueryDef时,选择“视图” /“ SQL视图”。 这显示(并允许编辑)QueryDef后面的SQL。
- 以编程方式,QueryDef对象具有一个名为.SQL的可更新字符串属性。 这将访问相同的数据。
在代码中,这更是一个问题。 考虑到这一点,我开发了一个简短的例程来安全地读取QueryDef的SQL。
'GetSQL gets the SQL component from a named query OR a SQL string.
'When subqueries are specified in MS Access they are changed internally
'from "FROM (SELECT blah blah blah) AS" to
'either "FROM [SELECT blah blah blah]. AS"
'or "FROM [SELECT blah blah blah] AS" both of which are invalid SQL.
'This code assumes any effected subquery will start with " [SELECT ".
'This reverts SQL to correct format and loses ';' at end if requested.
' 11/11/2004 Updated to detect second problem and to use InStr
Public Function GetSQL(strQuery As String, _
Optional blnLoseSC As Boolean = True) As String
Dim intDepth As Integer
Dim lngLeft As Long, lngOpen As Long, lngRight As Long, lngAdjust As Long
'If param passed is already SQL then leave as is - Otherwise get from query
If Left(strQuery, 1) = "(" Then
GetSQL = strQuery
Else
On Error Resume Next
GetSQL = CurrentDb.QueryDefs(strQuery).SQL
End If
lngLeft = -7
Do
'Check for corrupted subquery
lngLeft = InStr(lngLeft + 8, GetSQL, " [SELECT ", vbTextCompare)
If lngLeft = 0 Then Exit Do
'To find end correctly we must treat '[' & ']' as matched pairs
intDepth = 1
lngRight = lngLeft + 8
lngOpen = -lngRight
Do
'Find next ']'
lngRight = InStr(lngRight + 1, GetSQL, "]", vbBinaryCompare)
If lngRight = 0 Then
GetSQL = ""
Exit Function
End If
intDepth = intDepth - 1
Do
'For lngOpen negative numbers mean that item has been counted
'If already counted get next one - Otherwise drop through
If lngOpen < 0 Then _
lngOpen = InStr(-lngOpen + 1, GetSQL, "[", vbBinaryCompare)
'we're only interested (now) if it found one BEFORE the ']'
If lngOpen > lngRight Or lngOpen = 0 Then Exit Do
intDepth = intDepth + 1
lngOpen = -lngOpen
Loop
Loop While intDepth > 0
'If '].' found then be sure to drop the '.' too
lngAdjust = IIf(Mid(GetSQL, lngRight + 1, 1) = ".", 1, 0)
GetSQL = Left(GetSQL, lngLeft) & "(" & _
Mid(GetSQL, lngLeft + 2, lngRight - lngLeft - 2) & ")" & _
Right(GetSQL, Len(GetSQL) - (lngRight + lngAdjust))
Loop
'Lose ";" at end if requested and it exists
If blnLoseSC And Right(GetSQL, 3) = ";" & vbCrLf Then _
GetSQL = Left(GetSQL, Len(GetSQL) - 3)
End Function
好。
也许不太短。
From: https://bytes.com/topic/access/insights/794178-access-querydefs-mis-save-subquery-sql