2013-04-20 29 views
20

Trình xem thời gian dài lần đầu tiên. Tôi đang làm việc trên một ứng dụng cơ sở dữ liệu với giao diện người dùng trong Excel. Do đó tôi đang sử dụng VBA để truy cập cơ sở dữ liệu MySQL. Trình điều khiển tôi đang sử dụng là trình điều khiển ODBC (Windows) và tôi có một kết nối hợp lệ với cơ sở dữ liệu vì nhiều truy vấn khác hoạt động tốt. Những gì tôi đang cố gắng làm là trả về kết quả từ một loạt câu lệnh SQL thay vì cố gắng kết hợp tất cả thành một câu lệnh lớn (có thể sẽ hoạt động nhưng khó duy trì/hiểu). Tôi đã thêm cờ FLAG_MULTI_STATEMENTS = 67108864 vào chuỗi kết nối để chặn các lỗi cú pháp trình điều khiển.Recordset được trả lại bị đóng (mysql DB được truy cập thông qua ODBC trong VBA)

Nhưng bây giờ khi tôi chạy như sau:

queryDB.Open SQLquery, conn 

Các recordset (queryDB) cốt khép lại với không có lỗi rõ ràng. Câu lệnh sql có thể được tìm thấy here.

Tôi có thể đang phát sinh các lỗi không được trả lại cho VBA vì vậy mọi trợ giúp ở đây sẽ được đánh giá cao.

LƯU Ý: Câu lệnh sql hoạt động khi tôi có thể dán câu lệnh đó vào phpMyAdmin và trả về kết quả chính xác (không trống). Tôi không biết liệu các phát biểu cụ thể có phải là vấn đề hay không nhưng có lẽ việc sử dụng CREATE TEMPORARY TABLE ... hoặc sử dụng nhiều câu lệnh nói chung.

Ngoài ra tôi đoán rằng người lái xe có thể cố gắng để trả lại kết quả cho mỗi câu lệnh sql và VBA chỉ nhận được đầu tiên hoặc một cái gì đó ...

EDIT: báo cáo sql để tham khảo trong tương lai.

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

Tôi đã trả lời câu hỏi của riêng mình!

Bí mật nằm here:

Vì vậy, tôi đã đúng ở chỗ là có nhiều hơn một recordset trả lại. Tôi chỉ phải lặp qua chúng để tìm dữ liệu mà tôi muốn. Bộ sưu tập không được lập chỉ mục, do đó bạn phải tìm kiếm qua từng bộ sưu tập. Trong trường hợp của tôi, mỗi câu lệnh sql không trả về một recordset (đó là lý do tại sao recordset của tôi vẫn đóng khi tôi cố mở nó). Ngoại lệ duy nhất là câu lệnh sql cuối cùng trả về các bản ghi. vòng lặp của tôi trông giống như:

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

Chào mừng bạn đến với StackOverflow. Câu hỏi đầu tiên khá đẹp!Truy vấn của bạn nên được bao gồm ở đây thay vì tại pastebin mặc dù, để mọi người không phải rời khỏi trang web này để tìm ra những gì nó là bạn đang yêu cầu. (Chỉ có 50 dòng, vì vậy nó dễ dàng ở trong giới hạn ở đây.) (Các vấn đề khác là nếu liên kết với pastebin không có sẵn vì lý do nào đó, câu hỏi của bạn sẽ mất đi hầu hết ngữ cảnh của nó, làm cho người đọc trong tương lai trở nên vô nghĩa.) Bạn nên [sửa] và thêm vào đây thay vào đó. [Faq] có thêm thông tin về việc đặt câu hỏi tại đây. –

+0

Cảm ơn Ken. Tôi đã gửi sql của tôi để pastebin vào mục đích. Vì những lý do bạn vạch ra. Tôi không muốn nó được treo xung quanh mãi mãi! – Rossco

+0

Tuy nhiên, tôi sẽ chỉnh sửa bài đăng như được đề xuất vì tôi đã có vô số trợ giúp từ bài đăng của người khác trên trang web này và nhìn thứ hai không có bất kỳ điều gì trong sql mà tôi cân nhắc :-) – Rossco

Trả lời

1

trả lời sao chép từ cơ thể câu hỏi:

Tôi đã trả lời câu hỏi của riêng tôi!

Bí mật nằm here:

Vì vậy, tôi đã đúng ở chỗ là có nhiều hơn một recordset trả lại. Tôi chỉ phải lặp qua chúng để tìm dữ liệu mà tôi muốn. Bộ sưu tập không được lập chỉ mục, do đó bạn phải tìm kiếm qua từng bộ sưu tập. Trong trường hợp của tôi, mỗi câu lệnh sql không trả về một recordset (đó là lý do tại sao recordset của tôi vẫn đóng khi tôi cố mở nó). Ngoại lệ duy nhất là câu lệnh sql cuối cùng trả về các bản ghi. Vòng lặp của tôi trông giống như:

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 
Các vấn đề liên quan