【问题标题】:Excel VBA ADO SQL - Syntax error in From clauseExcel VBA ADO SQL - From 子句中的语法错误
【发布时间】:2016-04-17 08:25:16
【问题描述】:

VBA ADO 中的以下 SQL 给出了“From 子句中的语法错误”错误。

Sub RunSQL2()

    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim strFile As String
    Dim strCon As String
    Dim strSQL As String
    Dim ws As Worksheet
    Dim strRangeAddress As String
    Dim dataRange As Range

    strFile = ThisWorkbook.Path & "\" & ThisWorkbook.Name
    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _
        & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"

    Set cn = CreateObject("ADODB.Connection")
    Set rs = CreateObject("ADODB.Recordset")

    cn.Open strCon

    Set ws = ThisWorkbook.Sheets("mydata")
    strRangeAddress = ActiveSheet.Name & "$" & ws.Range("A1:C30020").Address(False, False)

        strSQL = strSQL & " (select s.* from "
strSQL = strSQL & " (select t.*, row_number() over (partition by child_level order by child_index,child_level) [rownum] from [" & strRangeAddress & "] t) s "
strSQL = strSQL & " where [rownum] = 1) u "
strSQL = strSQL & " join (select t2.*, 1 as  [rownum] from [" & strRangeAddress & "] t2) v "
strSQL = strSQL & " on (v.parent_level = u.child_level and v.[rownum] = u.[rownum]) "
strSQL = strSQL & " union select  w.child_index,w.child_level,w.child_level,w.child_index "
strSQL = strSQL & " from [" & strRangeAddress & "] w "
strSQL = strSQL & " where w.child_index = 1 "
strSQL = strSQL & " order by v.child_index;"


    rs.Open strSQL, cn

    Debug.Print rs.GetString

End Sub

strSQL的debug.print是:

select v.child_index,v.child_level,v.parent_level,u.child_index as  parent_index 
from  
  (select s.* 
   from  
     (select t.*, row_number() over (partition by child_level order by child_index,child_level) [rownum] 
      from [mydata$A1:C30020] t
     ) s  
   where [rownum] = 1
  ) u  
join 
  (select t2.*, 1 as  [rownum] 
   from [mydata$A1:C30020] t2
  ) v  on (v.parent_level = u.child_level and v.[rownum] = u.[rownum])  

union 

select  w.child_index,w.child_level,w.child_level,w.child_index  
from [mydata$A1:C30020] w  
where w.child_index = 1  
order by v.child_index;

当我使用简单的 strSQL 字符串时,连接工作并返回结果。这有效:

strSQL = "SELECT * FROM [" & strRangeAddress & "]"

我认为我的语法正确。错误是否可能是由不兼容的 SQL 引起的?比如ADO可以做'Partition by'吗?

我正在使用 Excel 2010 64 位 Office。

【问题讨论】:

  • 我已经重新格式化了您的长内联 SQL 查询,因为它根本无法理解。当评论被接受时,再次检查查询以确保这是正确的。稍后我会仔细研究您的问题
  • 专业提示:当您使用 strSQL = strSQL & 在代码中构建如此长而复杂的查询时,请在每行末尾添加 & vbcrlf 以便查询变得易于理解当你debug.print strSQL
  • 您用于连接 Excel 工作簿的 Jet/ACE SQL 引擎在其方言中不支持窗口函数,因此您不能使用 RowNumber()Over()Partition
  • 除了@Parfait 提到的问题之外,查询永远不会工作,因为UNION 要求您在第一部分和第二部分中具有相同数量的列。您的查询选择了 UNION 之前的 5 列和 UNION 之后的 4 列。
  • 感谢 Thomas 看起来很棒。我确实使用换行符,但在这个阶段我喜欢尽量减少复杂性。

标签: sql vba ado


【解决方案1】:

考虑使用相关计数聚合查询来代替窗口函数,因为此子查询应符合 Jet/ACE SQL:

SELECT v.child_index, v.child_level, v.parent_level, u.child_index, v.parent_index 
FROM
  (SELECT s.* 
   FROM  
     (SELECT t.*, (SELECT count(*) FROM [mydata$A1:C30020] sub 
                   WHERE sub.child_index <= t.child_index
                   AND sub.child_level = t.child_level) as [rownum] 
      FROM [mydata$A1:C30020] t
     ) s  
   WHERE [rownum] = 1
  ) u  
INNER JOIN 
  (SELECT t2.*, 1 as [rownum] 
   FROM [mydata$A1:C30020] t2
  ) v  
ON (v.parent_level = u.child_level) AND (v.[rownum] = u.[rownum])  

UNION 

SELECT w.child_index, w.child_level, w.parent_level, w.child_index, w.parent_index 
FROM [mydata$A1:C30020] w  
WHERE w.child_index = 1  
ORDER BY v.child_index;

【讨论】:

  • 我在意识到同样的问题后删除了您回答的问题。刚刚尝试了 VBA 中的 SQL,它给出了“没有为一个或多个必需参数提供值”错误。我不在具有 SQL Server 或 Access 的机器上,因此无法在 VBA 之外测试 SQL。
  • 您能否验证[mydata$A1:C30020] 的顶部标题是否具有完全符合指定的字段列:child_index、child_level、parent_level、child_index、parent_index。
  • 修正child_index,child_level,parent_level,child_index为parent_index
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-08
  • 1970-01-01
  • 2013-11-02
  • 2019-04-20
相关资源
最近更新 更多