Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returned Recordset is closed (mysql DB accessed via ODBC in VBA)

Tags:

mysql

excel

vba

Long time viewer first time poster. I'm working on a database application with a front-end in Excel. Hence I am using VBA to access a MySQL database. The driver I'm using is the ODBC driver (Windows) and I have a valid connection to the database as lots of other queries function well.

What I'm trying to do is return the results from a series of SQL statements rather than trying to combine it all into one massive statement (which would probably work but be difficult to maintain/understand). I have added the flag FLAG_MULTI_STATEMENTS = 67108864 to the connection string which suppressed driver syntax errors.

But now when I run the following:

queryDB.Open SQLquery, conn

The recordset (queryDB) remains closed with no apparent error. The sql statement can be found here.

I may be generating errors that aren't being returned to VBA so any help here would be much appreciated.

NOTE: The sql statements work as I can paste that statement into phpMyAdmin and it returns the correct (non-empty) results. I don't know if the statements specifically are the problem but perhaps the use of CREATE TEMPORARY TABLE ... or the use of multiple statements in general.

Also I guess that the driver may be trying to return a result for each sql statement and VBA is only getting the first or something...

EDIT: the sql statement for future reference.

CREATE TEMPORARY TABLE tmpOrders AS
SELECT
o.customerName,
SUM(o.Sales) AS Sales,
SUM(TotalFobCost + TotalLandedCost + TotalLocalCost + TotalCmtCost) AS TotalCost,
YEAR(o.deliveryDate) AS YEAR,
MONTH(o.deliveryDate) AS MONTH
FROM devere_costing.orders_fixed_extras AS o
WHERE o.orderApproved = TRUE
AND o.orderCanceled = FALSE
AND o.deliveryDate BETWEEN '2014-01-01' AND '2014-03-31'
GROUP BY customerName, YEAR, MONTH
ORDER BY YEAR ASC, MONTH ASC, customerName ASC;

CREATE TEMPORARY TABLE tmpProj AS
SELECT p.customerName,
   IF(p.MONTH > 9, p.YEAR, p.YEAR - 1) AS TrueYear,
   1 + ((p.MONTH + 2) MOD 12) AS TrueMonth,
   SUM(p.actualSalesInvoiced) AS salesInvoiced,
   SUM(p.budget) AS budget
FROM devere_costing.sales_projection_data AS p
GROUP BY p.customerName, p.YEAR, p.MONTH
HAVING TrueYear BETWEEN YEAR('2014-01-01') AND YEAR('2014-03-31')
AND TrueMonth BETWEEN MONTH('2014-01-01') AND MONTH('2014-03-31');

CREATE TEMPORARY TABLE tmpLeft AS
SELECT
IF(o.customerName IS NULL, p.customerName, o.customerName) AS customerName,
p.budget AS TotalBudget,
o.Sales AS Sales,
p.salesInvoiced,
0 AS varianceToBudget,
o.TotalCost,
0 AS directMargin,
0 AS directMarginPercent,
IF(o.YEAR IS NULL, p.TrueYear, o.YEAR) AS YEAR,
IF(o.MONTH IS NULL, p.TrueMonth, o.MONTH) AS MONTH
FROM tmpOrders AS o
LEFT JOIN tmpProj AS p
ON (o.customerName = p.customerName
AND o.YEAR = p.TrueYear
AND o.MONTH = p.TrueMonth);

CREATE TEMPORARY TABLE tmpRight AS
SELECT
IF(o.customerName IS NULL, p.customerName, o.customerName) AS customerName,
p.budget AS TotalBudget,
o.Sales AS Sales,
p.salesInvoiced,
0 AS varianceToBudget,
o.TotalCost,
0 AS directMargin,
0 AS directMarginPercent,
IF(o.YEAR IS NULL, p.TrueYear, o.YEAR) AS YEAR,
IF(o.MONTH IS NULL, p.TrueMonth, o.MONTH) AS MONTH
FROM tmpOrders AS o
RIGHT JOIN tmpProj AS p
ON (o.customerName = p.customerName
AND o.YEAR = p.TrueYear
AND o.MONTH = p.TrueMonth);

(SELECT * FROM tmpLeft) UNION DISTINCT (SELECT * FROM tmpRight);

I have answered my own question!

The secret lies here:

So I was right in that there was more than one recordset returned. I just had to iterate through them to find the data that I want. The collection isn't indexed so you have to search through each one. In my case every sql statement does not return a recordset (that's why my recordset remained closed when I tried to open it). The only exception is the last sql statement which returns records. My loop looks like:

Dim rs As ADODB.Recordset
Set rs = queryDB(Sql)

' Loop through returned recordsets to find the data
Do
    If Not rs Is Nothing Then
        If rs.State = adStateOpen Then
            ' we have an open recordset.  This means that the final select statement
            ' has returned this data.
            Exit Do
        Else
            ' Otherwise iterate through to the next recordset
            Set rs = rs.NextRecordset
        End If
    Else
        MsgBox "No recordset returned by sql statement"
        GoTo ExitCode
    End If
Loop
like image 680
Rossco Avatar asked Apr 20 '13 01:04

Rossco


1 Answers

Answer copied from the question body:

I have answered my own question!

The secret lies here:

So I was right in that there was more than one recordset returned. I just had to iterate through them to find the data that I want. The collection isn't indexed so you have to search through each one. In my case every sql statement does not return a recordset (that's why my recordset remained closed when I tried to open it). The only exception is the last sql statement which returns records. My loop looks like:

Dim rs As ADODB.Recordset
Set rs = queryDB(Sql)

' Loop through returned recordsets to find the data
Do
    If Not rs Is Nothing Then
        If rs.State = adStateOpen Then
            ' we have an open recordset.  This means that the final select statement
            ' has returned this data.
            Exit Do
        Else
            ' Otherwise iterate through to the next recordset
            Set rs = rs.NextRecordset
        End If
    Else
        MsgBox "No recordset returned by sql statement"
        GoTo ExitCode
    End If
Loop
like image 129
Bill the Lizard Avatar answered Oct 03 '22 09:10

Bill the Lizard