这两个语句相似,但第二个语句会导致 Excel 在每次执行时崩溃。唯一的区别是model
和model return updated rows
(我专门设计了这个最小的例子,以便查询在任何一种情况下都返回完全相同的数据,我的实际 SQL 当然是不同的):
select * from( select * from ( select 1 id, 100 val from dual union all select 2 id, 200 val from dual ) model dimension by (id) measures (val) rules ( val[1] = val[cv()]+1 ) ) where val=101
select * from( select * from ( select 1 id, 100 val from dual union all select 2 id, 200 val from dual ) model return updated rows dimension by (id) measures (val) rules ( val[1] = val[cv()]+1 ) ) where val=101
这是 ADO 中错误的一个孤立示例,还是存在使解析器崩溃的已知 SQL 语句类(我什至不确定为什么 ADO 会解析语句而不是将其传递给数据库)。
这是崩溃版本的完整 VBA 代码:
Option Explicit
Sub Go()
Dim lConn As ADODB.Connection
Dim lRecordset As ADODB.Recordset
'Dim lRecordset
Dim sSQL As String
Set lConn = New ADODB.Connection
Set lRecordset = New ADODB.Recordset
'Set lRecordset = CreateObject("ADODB.Recordset")
lConn.Open "Provider=MSDAORA;Data Source=(DESCRIPTION=(CID=GTU_APP)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=devdb)(PORT=1521)))(CONNECT_DATA=(SID=oracle)(SERVER=DEDICATED)));User Id=csuk;Password=thisisnotmyrealpassword;"
With lRecordset
sSQL = "select * " & _
"from( select * " & _
" from ( select 1 id, 100 val from dual " & _
" Union all " & _
" select 2 id, 200 val from dual ) " & _
" model return updated rows " & _
" dimension by(id) " & _
" measures (val) " & _
" rules ( val[1] = val[cv()]+1 ) ) " & _
"where val=101"
.Open sSQL, lConn
While Not .EOF
Sheets(1).Cells(1, 1) = ![Val]
.MoveNext
Wend
.Close
End With
Set lRecordset = Nothing
lConn.Close
Set lConn = Nothing
End Sub
作为对评论的回应,我使用 DAO 尝试了相同的 SQL,令我困惑的是,我们得到了相同的结果。以下代码使 Excel 崩溃,但只需删除return updated rows
它即可使其按预期工作:
Option Explicit
Sub Go()
Dim lWorkspace As DAO.Workspace
Dim lDatabase As DAO.Database
Dim lRecordset As DAO.Recordset
Dim sSQL As String
sSQL = "select * " & _
"from( select * " & _
" from ( select 1 id, 100 val from dual " & _
" Union all " & _
" select 2 id, 200 val from dual ) " & _
" model return updated rows " & _
" dimension by(id) " & _
" measures (val) " & _
" rules ( val[1] = val[cv()]+1 ) ) " & _
"where val=101"
Set lWorkspace = DBEngine.Workspaces(0)
Set lDatabase = lWorkspace.OpenDatabase("", False, False, "Driver={Microsoft ODBC for Oracle};Server=devdb:1521/oracle;Uid=charts_csuk_uksoft;Pwd=thisisnotmyrealpassword;")
Set lRecordset = lDatabase.OpenRecordset(sSQL, dbOpenDynaset, dbSQLPassThrough)
With lRecordset
While Not .EOF
Sheets(1).Cells(1, 1) = ![Val]
.MoveNext
Wend
End With
Set lRecordset = Nothing
Set lDatabase = Nothing
Set lWorkspace = Nothing
End Sub