Queste due istruzioni sono simili ma la seconda causa l'arresto anomalo di Excel ogni volta che viene eseguito. L'unica differenza è tra il model
e model return updated rows
(ho appositamente progettato questo esempio minimo in modo che le query restituiscono gli stessi dati in entrambi i casi, il mio SQL mondo reale è diverso, naturalmente):Come posso aggirare Excel in modo anomalo con determinate istruzioni SELECT?
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
è questo un esempio isolato di un bug in ADO o c'è una classe nota di istruzioni SQL che fanno cadere il parser (io non sono nemmeno sicuro perché ADO sarebbe analizzare l'istruzione, piuttosto che solo di passaggio è t attraverso il database).
Ecco il codice VBA in pieno per la versione che si blocca:
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
In risposta a un commento, ho provato lo stesso SQL utilizzando DAO, e al mio stupore, abbiamo ottieni lo stesso risultato. Il seguente codice si blocca Excel, ma la rimozione del return updated rows
è tutto quello che serve per farlo funzionare come previsto:
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
aggiungere 'Set lConn = Nothing' sotto' lConn.Close' per il collegamento gratuito alla connessione. Ora, Excel si blocca anche con l'associazione tardiva di ADODB.Recordset? Vedi anche [suggerimento] (http://www.vbforums.com/showthread.php?511763-Classic-VB-Why-shouldn-tI-use-quot-Dim-As-New-quot) relativo all'utilizzo di 'As new'. Che ne dici di utilizzare le alternative ADODB? Facci sapere se uno di questi aiuti –
Grazie, ho provato ad aggiungere 'set lConn = Nothing' e ho aggiornato la domanda con quel miglioramento. Ho anche provato l'associazione tardiva (vedi le righe commentate nella domanda modificata.) Nessuno dei due previene il crash, sarei interessato a sapere quali alternative ADODB suggeriresti di provare? –
Il primo a cui riesco a pensare è [DAO] (http://allenbrowne.com/ser-29.html). Un'altra opzione sarebbe quella di scrivere la tua libreria COM usando C# o VB.NET e aggiungere riferimenti alla tua 'dll' (come aggiungere altri riferimenti, ad esempio Microsoft Scripting Libreria) .Utilizzando una libreria COM è possibile creare oggetti personalizzati del proprio tipo in Excel. Detto questo, ti consentirebbe di passare le query direttamente alla libreria COM che la eseguirà sul tuo database saltando il parser ADODB ecc. usa 'Connessione SQL' dalla libreria' System.Data.SqlClient'. –