2013-08-14 60 views
6

Hai câu lệnh này tương tự nhau nhưng nguyên nhân thứ hai khiến Excel bị lỗi mỗi khi nó được thực hiện. Sự khác biệt duy nhất là giữa modelmodel return updated rows (tôi đã thiết kế đặc biệt ví dụ nhỏ này để các truy vấn trở lại chính xác cùng một dữ liệu trong cả hai trường hợp, SQL thực thế giới của tôi là khác nhau tất nhiên):Làm cách nào để làm việc xung quanh Excel gặp sự cố với một số câu lệnh SELECT?

  1. 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 
    
  2. 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 
    

đây có phải là một ví dụ đơn lẻ của một lỗi trong ADO hoặc là có một lớp tiếng của câu lệnh SQL mà sụp đổ phân tích cú pháp (tôi thậm chí không chắc chắn lý do tại sao ADO sẽ phân tích báo cáo kết quả hơn là chỉ đi nó t hrough vào cơ sở dữ liệu).

Dưới đây là đoạn code VBA trong đầy đủ cho phiên bản đó bị treo:

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 

Để đối phó với một lời nhận xét, tôi đã cố gắng cùng SQL sử dụng DAO, và bối rối của tôi, chúng tôi nhận được kết quả tương tự. Các mã sau đây bị treo Excel, nhưng loại bỏ các return updated rows là tất cả những gì cần thiết để làm cho nó làm việc như mong đợi:

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

thêm 'Đặt lConn = Nothing' bên dưới' lConn.Close' để liên kết miễn phí với kết nối. Bây giờ, Excel có gặp sự cố với sự ràng buộc muộn của ADODB.Recordset không? Ngoài ra, hãy xem [mẹo] này (http://www.vbforums.com/showthread.php?511763-Classic-VB-Why-shouldn-tI-use-quot-Dim-As-New-quot) liên quan đến việc sử dụng 'As Mới'. Làm thế nào về việc sử dụng các lựa chọn thay thế ADODB? Hãy cho chúng tôi biết nếu bất kỳ điều nào trong số này giúp được –

+0

Cảm ơn, tôi đã thử thêm 'set lConn = Nothing' và cập nhật câu hỏi với cải tiến đó. Tôi cũng đã cố gắng ràng buộc muộn (xem dòng bình luận trong câu hỏi sửa đổi. Không ai trong số này ngăn chặn sự sụp đổ, tôi muốn được biết những gì ADODB lựa chọn thay thế bạn đề nghị cố gắng? –

+0

Người đầu tiên tôi có thể nghĩ là [DAO] (http://allenbrowne.com/ser-29.html) Một tùy chọn khác là viết thư viện COM của riêng bạn bằng cách sử dụng C# hoặc VB.NET và thêm tham chiếu đến 'dll' của bạn (giống như thêm bất kỳ tham chiếu nào khác tức là Microsoft Scripting Sử dụng một thư viện COM cho phép bạn tạo các đối tượng của riêng bạn trong Excel, nói rằng nó sẽ cho phép bạn truyền các truy vấn trực tiếp đến thư viện COM, nó sẽ thực thi nó đối với cơ sở dữ liệu của bạn bỏ qua trình phân tích cú pháp ADODB. sử dụng 'SQL Connection' từ thư viện' System.Data.SqlClient' –

Trả lời

2

Đây là chi tiết của một workaround, hơn giải pháp, nhưng nó có thể là một lựa chọn để ẩn bất kỳ câu lệnh SQL, ADO xáo trộn (hoặc Excel, cho rằng vấn đề), sau VIEW. Đối với báo cáo động (tức là thay đổi lượt xem trong thời gian chạy), bạn có thể xem xét sử dụng các thủ tục với EXECUTE IMMEDIATE CREATE OR REPLACE VIEW ... trong đó.

+1

Đây là khoảng những gì tôi đã làm, cảm ơn. ADO có vẻ khá hài lòng với 'lConn.Execute" tạo view v_sidNNN là "& sSQL" 'và' select * từ v_sidNNN'. –

1

Bạn có thể tránh cú pháp rắc rối bằng cách xây dựng một phiên bản tùy chỉnh của return updated rows.

Thêm cột giả để theo dõi những gì đã được cập nhật và khởi tạo nó thành false (0). Sau đó, thêm một số đo và cho mỗi quy tắc tạo một quy tắc tương tự sẽ đặt cờ thành đúng (1). Cuối cùng, thêm vị từ để chỉ bao gồm các hàng có cờ là 1.

Đây rõ ràng không phải là giải pháp lý tưởng. Nó sẽ chậm hơn. Và bạn phải nhớ xây dựng tất cả các quy tắc bổ sung để điền cờ.

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 

Cập nhật

Dưới đây là một vài ý tưởng.

  1. Bạn có thể chuyển sang phần mềm của Oracle không? Chương trình con đầu tiên của bạn làm việc cho tôi nếu tôi sử dụng Provider=ORAOLEDB.ORACLE. Và chương trình con thứ hai của bạn hoạt động nếu tôi sử dụng một DSN của Oracle. Tôi không thể nhận được MSDAORA hoặc {Microsoft ODBC for Oracle} để kết nối hoàn toàn với máy của mình. (Mặc dù đó có thể là lỗi của tôi.)
  2. Hãy thử thay đổi model return updated rows thành model keep nav return updated rows main main_model. Đây là một thay đổi vô nghĩa về ngữ nghĩa, chỉ cần liệt kê rõ ràng các giá trị mặc định. Nhưng có lẽ nó đủ để tránh lỗi phân tích cú pháp mà bạn đang gặp phải.
+1

Tôi đã biết tôi có thể làm việc xung quanh nó như thế này, nhưng tôi đánh giá cao nỗ lực, cảm ơn. Bạn có thể biết điều này nhưng bạn không cần phải thêm 'is_updated_or_inserted' vào bảng nguồn, bạn [có thể thêm nó vào các số đo] (http://sqlfiddle.com/#!4/d41d8/15863). –

+0

Những gợi ý hay, tôi đã cố gắng thử chèn các chú thích bên trong mệnh đề 'return updated rows' nhưng không phải như vậy hoặc toàn bộ dòng' main nav return updated main main_model' đều có hiệu lực. Chúng tôi hiện không có nhà cung cấp Oracle được cài đặt trong môi trường của chúng tôi để kiểm tra. Tôi đã đạt đến giai đoạn mà tôi nghĩ rằng tôi sẽ đi với một workaround: có thể tạo và thả quan điểm với sid trong tên. –