【问题标题】:VBA SQL query with WHERE clause带有 WHERE 子句的 VBA SQL 查询
【发布时间】:2018-08-12 23:15:11
【问题描述】:

我正在尝试编写 VBA 代码以将 SQL 数据导入 Excel。除了WHERE 条件外,一切正常。我认为问题可能出在报价上。这是我的查询:

Sub Engineering_Milestone()

Dim v_project As String
Dim cn  As ADODB.Connection
Dim rs  As ADODB.Recordset
Dim sql As String

Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset

v_project = Worksheets("Parameters").Range("B1").Value

'cn.Open "Provider = x.1; Data Source=x; Initial Catalog=x; Integrated Security=x"


cn.Open "Provider = Sx; Data Source=x; Initial Catalog=x; Integrated Security=x"

Worksheets("Engineering_Milestone").Range("A2:G5000").ClearContents

sql = " SELECT A.ENGINEER_ID, B.[Description], B.BUDGET_APPROVED, A.MILESTONE, A.[DESCRIPTION], A.PCT_COMPLETE, A.SCHEDULE_DATE FROM X as A  Inner Join X as B on A.ENGINEER_ID = B.ENGINEER_ID WHERE B.Project_ID = " & "'" & v_project & "'" and A.Project_ID = " & "'" & v_project & "'"

rs.Open sql, cn

Sheets("Engineering_Milestone").Cells(2, 1).CopyFromRecordset rs

rs.Close
cn.Close

End Sub

当 SQL 查询有一个条件时,它可以正常工作,即 ...where B.Project_ID = " & "'" & v_project & "'"(没有第二个条件 -> and A.Project_ID = " & "'" & v_project & "'")。

我对此很陌生,如果有人能提供帮助,我将不胜感激......非常感谢。

【问题讨论】:

  • 请解释“作品/从事的工作”。你有错误吗?你想做什么?这些是什么类型的字段?
  • v_project 是数字吗?
  • v_project 是一个字符串,比如 A.Project_ID = 'K34'

标签: sql vba excel where-clause


【解决方案1】:

正如我所说,永远不要通过字符串连接编写 SQL 代码,使用参数。看到你的代码后,现在更容易了:

Sub Engineering_Milestone()

Dim v_project As String
Dim cn  As ADODB.Connection
Dim rs  As ADODB.Recordset
Dim sql As String
Dim cmd as ADODB.Command

Set cn = New ADODB.Connection

v_project = Worksheets("Parameters").Range("B1").Value

'cn.Open "Provider = x.1; Data Source=x; Initial Catalog=x; Integrated Security=x"


cn.Open "Provider = Sx; Data Source=x; Initial Catalog=x; Integrated Security=x"

Worksheets("Engineering_Milestone").Range("A2:G5000").ClearContents

sql = "SELECT A.ENGINEER_ID, B.[Description], B.BUDGET_APPROVED, " & _
      "   A.MILESTONE, A.[DESCRIPTION], A.PCT_COMPLETE, A.SCHEDULE_DATE" & _
      " FROM X as A" & _
      " Inner Join X as B " & _
      "   on A.ENGINEER_ID = B.ENGINEER_ID and B.Project_ID = A.Project_ID" & _
      " WHERE B.Project_ID = ?"

  set cmd = New ADODB.Command
  cmd.ActiveConnection = cn
  cmd.CommandText = sql
  cmd.Parameters.Append cmd.CreateParameter("@projectId", adVarchar)
  cmd.Parameters("@projectId").Value = v_project

  Set rs = cmd.Execute()

  Sheets("Engineering_Milestone").Cells(2, 1).CopyFromRecordset rs

rs.Close
cn.Close

End Sub

注意:您的 SQL 确实含糊不清。你正在做一个自我加入只是为了创建某种笛卡尔加入?可能实际上engineerId、projectId的组合是独一无二的。如果这是正确的,那么您可以简化您的 SQL:

sql = "SELECT ENGINEER_ID, [Description], BUDGET_APPROVED, " & _
      "   MILESTONE, [DESCRIPTION], PCT_COMPLETE, SCHEDULE_DATE" & _
      " FROM X" & _
      " WHERE Project_ID = ?"

【讨论】:

  • 非常感谢@Parfait,您的帮助很大。再次道歉,因为我对此很陌生。我只是简单地修改了你的 SQL,它起作用了 :)
  • @TAG,欢迎。我的名字不是 Parfait,实际上编辑并没有改变任何东西(我不知道为什么要完成编辑):)
  • @CetinBasoz ...我只是对您的代码进行了格式化,以便它可以使用适当的颜色来遵守 VBA,我只是在其中添加了:<!-- language: vba -->
  • @Parfait,谢谢!我不知道你可以添加语言标签。顺便说一句,后来我看到了你的代码。这也是正确的,OP只需要添加值。
【解决方案2】:

你只提供了一行代码的一半,所以我只能猜测这就是你想要的:

"where B.Project_ID = '"& v_project &"'& And A.Project_ID = ' & v_project  "'"

在输入/退出多种类型的引号时,字符串可能会令人困惑,但当您解决构建字符串的问题时,请开始删除所有变量并仅使用硬编码的 SQL 字符串。

一旦生效,开始用变量(和适当的引号)一次替换一个值。

【讨论】:

  • sql = " SELECT A.ENGINEER_ID, B.[Description], B.BUDGET_APPROVED, A.MILESTONE, A.[DESCRIPTION], A.PCT_COMPLETE, A.SCHEDULE_DATE FROM X as A Inner Join X作为 A.ENGINEER_ID = B.ENGINEER_ID 上的 B,其中 B.Project_ID = " & "'" & v_project & "'"
  • 这是完整的 sql 查询...我尝试了您的代码,但不幸的是它不起作用:(。v_project 是一个字符串
  • sql = " SELECT A.ENGINEER_ID, B.[Description], B.BUDGET_APPROVED, A.MILESTONE, A.[DESCRIPTION], A.PCT_COMPLETE, A.SCHEDULE_DATE FROM X as A Inner Join X作为 A.ENGINEER_ID = B.ENGINEER_ID 上的 B,其中 B.Project_ID = " & "'" & v_project & "'" 和 A.Project_ID = " & "'" & v_project & "'"
【解决方案3】:

考虑 SQL 参数化,这是将值传递到 SQL 查询时的行业最佳实践 - 不仅在 VBA 或您的数据库中,而且跨 所有 语言接口到 任何 数据库。由于您不再担心报价,因此此过程更具可读性和可维护性。另外,代码(SQL 查询)与数据(VBA 变量)是分开的。

使用 ADO,可以使用Command Object 定义和设置参数。

Dim v_project As String, sql As String
Dim cn  As New ADODB.Connection
Dim rs  As New ADODB.Recordset
Dim cmd As New ADODB.Command

v_project = Worksheets("Parameters").Range("B1").Value

cn.Open "Provider = Sx; Data Source=x; Initial Catalog=x; Integrated Security=x"

' PREPARED STATEMENT WITH QMARK PLACEHOLDERS
sql = "SELECT A.ENGINEER_ID, B.[Description], B.BUDGET_APPROVED, A.MILESTONE," _
       & "    A.[DESCRIPTION], A.PCT_COMPLETE, A.SCHEDULE_DATE" _
       & " FROM X AS A INNER JOIN X as B ON A.ENGINEER_ID = B.ENGINEER_ID" _
       & " WHERE B.Project_ID = ? AND A.Project_ID = ?"

' COMMAND OBJECT 
Set cmd = New ADODB.Connection

With cmd
    .ActiveConnection = cn    ' CONNECTION OBJECT
    .CommandText = sql
    .CommandType = adCmdText

    ' BINDING PARAMETERS
    .Parameters.Append .CreateParameter("a_projid", adVarChar, adParamInput, , v_project)
    .Parameters.Append .CreateParameter("b_projid", adVarChar, adParamInput, , v_project)
End With

' ASSIGN TO RECORDSET
Set rs = cmd.Execute

With Worksheets("Engineering_Milestone")
     .Range("A2:G5000").ClearContents
     .Cells(2, 1).CopyFromRecordset rs
End With

rs.Close: cn.Close
Set cmd = Nothing: Set rs = Nothing: Set cn = Nothing

【讨论】:

  • 非常感谢@Parfait 的回复,我复制粘贴了您的代码(更改了 X),但仍然出现错误。我还需要与此代码一起做其他事情吗?非常感谢
  • 错误是什么?始终按照上面的评论包含它。
【解决方案4】:

永远不要编写像连接字符串那样的 SQL 代码。而是简单地使用参数。即:(说vProject是整数)

.. where B.Project_ID = ? And A.Project_ID = ?

cmd.Parameters.Append .CreateParameter("@projectId", adInteger, adParamInput, 0, vProject)
cmd.Parameters.Append .CreateParameter("@projectId", adInteger, adParamInput, 0, vProject)

注意:cmd 是您用于命令的 ADODB.Command 对象。

【讨论】:

  • 很好的答案,但要扩展它。 OP 或未来的读者不会知道 cmd 应该是什么。
  • 您在查询中使用?,但在CreateParameter 中使用@projectId。我说的对吗?
  • 是的,完全正确。 OLEDB 参数不是命名的,而是位置的。创建的顺序很重要,名称可以是任何你喜欢的,我使用“@projectId”只是@前缀在 MS 世界(即 MS SQL 服务器)中很常见。它可能是“anyNameILike_OnlyIsForDeveloper”。
猜你喜欢
  • 2016-03-11
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多