2013-04-20 2 views
20

Долгое время зритель впервые плакат. Я работаю над приложением базы данных с интерфейсом в Excel. Поэтому я использую VBA для доступа к базе данных MySQL. Драйвер, который я использую, является драйвером ODBC (Windows), и у меня есть действующее соединение с базой данных, так как многие другие запросы хорошо работают.Возвращенный набор записей закрыт (mysql DB, доступ к которому осуществляется через ODBC в VBA)

То, что я пытаюсь сделать, это вернуть результаты из ряда операторов SQL, а не пытаться объединить все это в одно массовое утверждение (которое, вероятно, будет работать, но будет трудно поддерживать/понимать). Я добавил флаг FLAG_MULTI_STATEMENTS = 67108864 в строку подключения, которая подавила ошибки синтаксиса драйверов.

Но теперь, когда я запускаю следующее:

queryDB.Open SQLquery, conn 

В recordset (queryDB) остается закрытым без видимых ошибок. Оператор sql может быть найден here.

Возможно, я генерирую ошибки, которые не возвращаются в VBA, поэтому любая помощь здесь будет высоко оценена.

ПРИМЕЧАНИЕ: Операторы sql работают, так как я могу вставить этот оператор в phpMyAdmin и он возвращает правильные (непустые) результаты. Я не знаю, являются ли утверждения специфически проблемой, но, возможно, использование CREATE TEMPORARY TABLE ... или использование нескольких операторов в целом.

Кроме того, я предполагаю, что водитель может попытаться вернуть результат для каждого SQL заявления и VBA только получение первого или что-то ...

EDIT: оператор SQL для дальнейшего использования.

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); 

Я ответил на свой вопрос!

Секрет кроется here:

Так что я был прав в том, что там было больше, чем один вернулся записей. Мне просто нужно было проходить через них, чтобы найти нужные мне данные. Коллекция не индексируется, поэтому вам нужно выполнить поиск по каждому из них. В моем случае каждый sql-оператор не возвращает набор записей (поэтому мой набор записей оставался закрытым, когда я пытался его открыть). Единственным исключением является последняя инструкция sql, которая возвращает записи. Мой цикл выглядит следующим образом:

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 
+6

Добро пожаловать в StackOverflow. Довольно хороший первый вопрос!Ваш запрос должен быть включен здесь, а не в pastebin, хотя, чтобы люди не покидали этот сайт, чтобы выяснить, что вы спрашиваете. (Это всего лишь около 50 строк, поэтому здесь легко находиться в пределах.) (Другие проблемы заключаются в том, что если по какой-то причине ссылка на пастебин недоступна, ваш вопрос теряет большую часть своего контекста, что делает его бессмысленным для будущих читателей). Вы должны [изменить] и добавить его здесь. [Faq] имеет больше информации о задании вопросов здесь. –

+0

Спасибо Кен. Я специально разместил свой sql для пастихина. По причинам, которые вы указали. Я не хотел, чтобы он вешал вечно! – Rossco

+0

Однако я отредактирую сообщение, как было предложено, так как у меня была большая помощь от сообщений других на этом сайте, а во втором - нет ничего в sql, который я бы счел конфиденциальным :-) – Rossco

ответ

1

Ответ скопированного из тела вопроса:

Я ответил на свой вопрос!

Секрет кроется here:

Так что я был прав в том, что там было больше, чем один вернулся записей. Мне просто нужно было проходить через них, чтобы найти нужные мне данные. Коллекция не индексируется, поэтому вам нужно выполнить поиск по каждому из них. В моем случае каждый sql-оператор не возвращает набор записей (поэтому мой набор записей оставался закрытым, когда я пытался его открыть). Единственным исключением является последняя инструкция sql, которая возвращает записи. Моя петля выглядит так:

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