这两个语句类似,但第二个语句导致Excel每次执行时崩溃。唯一的区别是model
和model return updated rows
之间(我特意设计了这个最小的示例,以便在任何一种情况下查询都返回完全相同的数据,我的实际SQL当然是不同的):< / p>
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
答案 0 :(得分:2)
这是一种解决方法,而不是解决方案,但它可能是隐藏任何SQL语句的选项,在VIEW
之后隐藏ADO(或Excel)。对于动态语句(即在运行时更改视图),您可以考虑使用其中包含EXECUTE IMMEDIATE CREATE OR REPLACE VIEW ...
的过程。
答案 1 :(得分:1)
您可以通过构建return updated rows
的自定义版本来避免麻烦的语法。
添加假列以跟踪已更新的内容,并将其初始化为false(0)。然后添加一个度量,并为每个规则创建一个类似的规则,将标志设置为true(1)。最后,添加一个谓词,仅包含标志为1的行。
这显然不是一个理想的解决方案。它会慢一些。你必须记住建立 填充旗帜的所有额外规则。
select id, val
from( select *
from ( select 1 id, 100 val, 0 is_updated_or_inserted from dual
union all
select 2 id, 200 val, 0 is_updated_or_inserted from dual
union all
select 3 id, 101 val, 0 is_updated_or_inserted from dual )
model
dimension by (id)
measures (val, is_updated_or_inserted)
rules ( val[1] = val[cv()]+1 , is_updated_or_inserted[1] = 1) )
where val=101
and is_updated_or_inserted = 1
<强>更新强>
以下是一些其他想法。
Provider=ORAOLEDB.ORACLE
,您的第一个子程序将适用于我。如果我使用Oracle DSN,您的第二个子例程也可以工作。我无法在我的计算机上连接MSDAORA
或{Microsoft ODBC for Oracle}
。 (虽然这可能是我的错。)model return updated rows
更改为model keep nav return updated rows main main_model
。这是一个语义无意义的变化,它只是
明确列出默认值。但也许这足以避免你遇到的解析错误。