VBA SQL 带 WHERE 子句的查询
VBA SQL query with 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 & "'"
)。
我对此很陌生,如果有人能提供帮助,我将不胜感激...非常感谢。
您只提供了一行代码的一半,所以我只能猜测这就是您的目的:
"where B.Project_ID = '"& v_project &"'& And A.Project_ID = ' & v_project "'"
当 entering/exiting 多种类型的引号时,字符串可能会令人困惑,但是当您解决构建字符串的问题时,请开始删除所有变量并仅使用硬编码 SQL细绳。
一旦成功,开始一次用变量(和适当的引号)替换值。
切勿编写 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 对象。
考虑 SQL 参数化,这是将值传递到 SQL 查询时的行业最佳实践 - 不仅在 VBA 或您的数据库中,而且在 所有 [=18] 中=] 到 any 数据库的语言接口。这个过程更具可读性和可维护性,因为您不再担心报价。另外,代码(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
正如我所说,永远不要通过字符串连接编写 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 = ?"
我正在尝试编写 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 & "'"
)。
我对此很陌生,如果有人能提供帮助,我将不胜感激...非常感谢。
您只提供了一行代码的一半,所以我只能猜测这就是您的目的:
"where B.Project_ID = '"& v_project &"'& And A.Project_ID = ' & v_project "'"
当 entering/exiting 多种类型的引号时,字符串可能会令人困惑,但是当您解决构建字符串的问题时,请开始删除所有变量并仅使用硬编码 SQL细绳。
一旦成功,开始一次用变量(和适当的引号)替换值。
切勿编写 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 对象。
考虑 SQL 参数化,这是将值传递到 SQL 查询时的行业最佳实践 - 不仅在 VBA 或您的数据库中,而且在 所有 [=18] 中=] 到 any 数据库的语言接口。这个过程更具可读性和可维护性,因为您不再担心报价。另外,代码(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
正如我所说,永远不要通过字符串连接编写 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 = ?"