我正在尝试编写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 & "'"
)时,它可以很好地工作。
我对此很陌生,所以如果有人可以帮助我将不胜感激……非常感谢。
答案 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对象。