【问题标题】:Query containing a CTE running against OLEDB provider failing on one computer but working on another包含针对 OLEDB 提供程序运行的 CTE 的查询在一台计算机上失败但在另一台计算机上运行
【发布时间】:2014-02-11 12:33:17
【问题描述】:

我有以下 VBScript 代码,它在我的计算机 (Windows 7 SP1) 上运行良好,但无法在另一台计算机 (Windows XP SP3) 上运行:

Dim objConn 'adodb connection object
Dim objRS 'adodb recordset object
Dim strQuery
Const adOpenStatic = 3
Const adLockReadOnly = 1
Set objConn = CreateObject("ADODB.Connection")
Set objRS = CreateObject("ADODB.Recordset")
objConn.Open "Provider=sqloledb;Data Source=" & strDBServer & ";Initial Catalog=BromsunInfo;Integrated Security=SSPI;"

strQuery = _
    "WITH CMSRATES AS " & _
    "( " & _
    "SELECT h.EMPL_UNO, h.employee_code, r.rate 'Rate', r.eff_date 'Eff Date' " & _
    "FROM " & strCMSDBServer & ".cmsopen.dbo.hbm_persnl h, " & strCMSDBServer & _
    ".cmsopen.dbo.tbm_persnl p, " & strCMSDBServer & ".CMSOPEN.dbo.TBM_RATE_FEE r " & _
    "WHERE h.empl_uno = p.empl_uno " & _
    "AND p.empl_uno = r.empl_uno " & _
    "AND R.EFF_DATE = " & _
    "(SELECT MAX(EFF_DATE) " & _
    "FROM " & strCMSDBServer & ".cmsopen.dbo.TBM_RATE_FEE R2 " & _
    "WHERE R2.RATE_LEVEL = '1' and member_type='1' AND R2.GROUP_TYPE = '4' AND R2.EMPL_UNO = P.EMPL_UNO) " & _
    "AND r.rate_level = '1' " & _
    "AND r.group_type = '4' " & _
    "AND r.member_type='1' " & _
    ") " & _
    "SELECT bu.UserID, cr.Rate, cr.EMPL_UNO " & _
    "FROM " & strDBServer & ".BromsunInfo.dbo.BromsunUsers bu " & _
    "INNER JOIN CMSRATES cr " & _
    "ON cr.employee_code = bu.Initials " & _
    "ORDER BY bu.UserDisplayName"

With objRS
    .Open strQuery, objConn, adOpenStatic, adLockReadOnly

    'Do stuff here

    .Close
End With

objConn.Close()

我在调用 objRS.Open 时遇到的错误是 Incorrect syntax near the keyword 'WITH',这表明它不喜欢我使用 CTE。这是脚本之外的查询:

WITH CMSRATES AS
(
    SELECT h.EMPL_UNO, h.employee_code, r.rate 'Rate', r.eff_date 'Eff Date'
    FROM cmsopen.dbo.hbm_persnl h, cmsopen.dbo.tbm_persnl p, CMSOPEN.dbo.TBM_RATE_FEE r 
    WHERE h.empl_uno = p.empl_uno 
    AND p.empl_uno = r.empl_uno 
    AND R.EFF_DATE = 
    (SELECT MAX(EFF_DATE) 
    FROM cmsopen.dbo.TBM_RATE_FEE R2 
    WHERE R2.RATE_LEVEL = '1' and member_type='1' AND R2.GROUP_TYPE = '4' AND R2.EMPL_UNO = P.EMPL_UNO) 
    AND r.rate_level = '1' 
    AND r.group_type = '4' 
    AND r.member_type='1' 
)

SELECT bu.UserID, cr.Rate, cr.EMPL_UNO
FROM dbo.BromsunUsers bu
INNER JOIN CMSRATES cr
ON cr.employee_code = bu.Initials
WHERE ISNULL(bu.BillingRate, -1)<>cr.Rate
ORDER BY bu.UserDisplayName

我想知道与 XP 机器相比,我的 Windows 7 机器上的 OLEDB 驱动程序是否有什么不同。不过,我不明白驱动程序的版本有什么影响,因为查询最终会在数据库服务器上运行。

任何帮助将不胜感激。

【问题讨论】:

  • 你有没有机会在服务器上进行某种负载平衡?也许它在两个不同版本的 SQL 之间平衡你(这确实很奇怪,但谁知道)?
  • @Joe -- 不,没有负载平衡。
  • 您确定要连接到同一台服务器吗?如果是这样,那么它必须是驱动程序 - 驱动程序的相同版本?
  • @Hogan -- 是的,绝对是同一台服务器。我用谷歌搜索但无法弄清楚如何获得 OLEDB 驱动程序。 ODBC 很简单,但不是 OLEDB。对此有任何想法吗?我会继续寻找。
  • @Joe -- 感谢您的建议。我使用分析器查看它传递了什么,它们实际上是不同的。有问题的计算机首先将 Exec 添加到我的陈述的乞求中,因为这失败了,它尝试在 Select * 前添加。

标签: sql-server sql-server-2008 oledb common-table-expression adodb


【解决方案1】:

从以下位置更改您的代码:

WITH CMSRATES AS
(

到这里:

;WITH CMSRATES AS
(

从技术上讲,CTE 不必以分号为前缀,但同一批次中的前一条语句必须以一个结尾。在其中一种情况下,提供程序或代码的其他部分很可能会随批处理一起发送其他命令(可能像 SET NOCOUNT ON 一样简单)。

顺便说一句,这正是为什么我所有涉及 CTE 的答案看起来都像后者,而不是前者(以及为什么我的所有代码示例都以 ; - more info on that here 终止每个相关语句)。在我的 Stack Overflow 职业生涯的早期,我犯了一个错误,即提供以 CTE 开头的答案,人们会将该代码复制并粘贴到现有批次中,而他们根本不使用分号。突然间,我因造成了一个我无法预料的语法错误而受到指责。 :-)

【讨论】:

  • 做到了!我喜欢堆栈溢出。非常感谢,亚伦。
  • @roryap *你爱亚伦。 (FTFY)
【解决方案2】:

除了 Aaron 的出色建议之外,当您有这样的差异时,您应该在服务器上检查(使用 SQL Server Profiler 或其他东西)每台机器正在传递什么。正如 Aaron 建议的那样,通过添加 ; 或其他更显着的差异可以解决问题机器在 with 之前传递的内容。

【讨论】:

  • 是的。我刚刚确认了这一点(请参阅我在我的问题下对您的评论的回复)。
猜你喜欢
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-26
  • 1970-01-01
  • 2011-03-30
相关资源
最近更新 更多