带WHERE子句的VBA SQL查询

时间:2018-08-11 21:06:29

标签: sql excel vba excel-vba where-clause

我正在尝试编写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 & "'")时,它可以很好地工作。

我对此很陌生,所以如果有人可以帮助我将不胜感激……非常感谢。

4 个答案:

答案 0 :(得分:1)

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

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

在输入/退出多种类型的引号时,字符串可能会造成混淆,但是在解决构建字符串的问题时,请先删除所有变量,然后仅使用硬编码的SQL字符串。

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

答案 1 :(得分:1)

考虑将SQL参数化,这是将值传递到SQL查询中的行业最佳实践-不仅在VBA或您的数据库中,而且跨 all 语言接口连接到任何数据库。由于您不再担心报价,因此该过程更具可读性和可维护性。另外,代码(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

答案 2 :(得分: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 = ?"

答案 3 :(得分:0)

永远不要编写像连接字符串这样的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对象。