如何在SQL插入语句中直接使用变量

时间:2019-06-29 14:44:12

标签: sql vba ms-access variables

我有一条SQL语句:

Dim Xdb As DAO.Database
Set Xdb = CurrentDb
Dim v1 As Integer
Dim v2 As String
With Me
    v1 = 1
    v2 = Trim(.txt2)
End With
Dim Sql As String
Sql = "Insert Into TblCustomers" _
& " (ID,FName)" _
& " Values " _
& " (1,'"& v2 &"')"

我想在SQL语句的值中使用此变量“ V2”,但不使用引号。

赞:

Sql = "Insert Into TblCustomers" _
& " (ID,FName)" _
& " Values " _
& " (1,v2)"

如何正确设置“ V2”变量呢?

3 个答案:

答案 0 :(得分:2)

您需要使用以下内容:

Dim cmdSQLInsert As ADODB.Command
Set cmdSQLInsert = New ADODB.Command

'Create the query
cmdSQLInsert.CommandText = "Insert Into TblCustomers(ID, FName) Values(?,?)"
cmdSQLInsert.CommandType = adCmdText
cmdSQLInsert.Prepared = True

'Create the parameters
'in this case we will create three parameters
'-----Param 1 (for Field ID)-------------
Dim gParam As ADODB.Parameter
Set gParam = New ADODB.Parameter
With gParam
    .Name = "ID"
    .Direction = adParamInput
    .Type = adInt
    .Value = 1
End With
cmdSQLInsert.Parameters.Append gParam

'-----Param 2 (for FName)-------------
Set gParam = Nothing
Set gParam = New ADODB.Parameter
With gParam
    .Name = "FName"
    .Direction = adParamInput
    .Type = adVarChar
    .Size = 50
    .Value = "FirstNameValue"
End With
cmdSQLInsert.Parameters.Append gParam

'Set the connection property of the command object
Set cmdSQLInsert.ActiveConnection = mySQLConnection

'Execute the command
cmdSQLInsert.Execute

答案 1 :(得分:0)

该问题确实是其他问题(例如,herehere)的重复,因为许多Access新手都希望并且希望能够直接从SQL语句中引用VBA变量。无论是INSERT,UPDATE,SELECT等,基本上都是相同的问题。

几乎所有好的答案最终都会导致使用参数化的QueryDefs或ADO命令,并且我同意这是出于各种原因的最佳实践方法。但是很少有评论和答案可以直接解决这个问题,所以这是另一种答案...

Access SQL无法直接引用VBA模块变量。但是,有两种可行的替代方法,但是它们都有各自的缺点。

  • 访问SQL 可以直接引用VBA模块中声明的公共函数。因为VBA函数实际上可以访问任何其他变量或对象并返回值,所以它肯定可以返回SQL不能直接访问的变量值。
    • 要实现的最关键问题是在执行查询之前,必须确保调用此函数的上下文。如果引用此类函数的查询曾经被称为“乱序”(当未正确初始化变量时),那么它当然会导致预期的行为和/或无效的数据。

'* From within a VBA module *
Private moduleVariable As String

Public Sub MySub()
  moduleVariable
End Sub

Public Function GetModuleVariable() As String
  GetModuleVariable = moduleVariable
End Function

'--- Example SQL statement ---
'INSERT INTO TblCustomers (ID,FName) VALUES (1, GetModuleVariable())
  • 可以访问的特殊对象称为TempVarsdocs here)。它实际上是为与宏一起使用而设计的,但是Access将其公开为可从SQL语句直接访问的对象,因此从技术上讲是允许的。
    • 最大的缺点是值存储为VBA变体,并且SQL并不总是正确地解释它们。使用显式转换函数可以解决此问题。该示例通过将TempVars引用包装在CDbl()中来说明这一点。

'* From within a VBA module *
Public Sub MySub()
  TempVars.Add "myVariable", 123.45
End Sub

'--- Example SQL statement ---
'INSERT INTO products (ID, Amount) VALUES (100, CDbl(TempVars!myVariable))

答案 2 :(得分:0)

我刚开始使用Access,发现接受的答案非常有帮助。谢谢@Pablo Santa Cruz。

我一直在寻找一种有助于消除代码中SQL注入的解释。当我实现此代码时,我遇到了参数中未设置值的问题。我将引用更改为使用索引,Parameters(0)等,然后由于我将所有参数声明为字符串而导致数据类型不匹配。

当我跟踪该过程时,我看到将INSERT语句分配给cmd.CommandText时,会自动添加参数,以匹配数据库中的元数据。因此,必须更改参数2和3才能分别匹配声明的参数类型,即整数和日期时间。

Kinda很酷,也许有点令人毛骨悚然。这是我的示例:

' Create table MyTable( sCol Varchar(255), nCol Integer, dCol DateTime )

Dim conn As New ADODB.Connection
conn.ConnectionString = "Provider=SQLOLEDB.1;Trusted_Connection=yes;Server=Thresher;Database=MyDB;"
conn.Open

Dim cmd As New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandText = "INSERT INTO MyTable( sCol, nCol, dCol ) VALUES (?, ?, ?)"

cmd.Parameters(0).Value = "One"
cmd.Parameters(1).Value = 1
cmd.Parameters(2).Value = #1/1/2001#
cmd.Execute

conn.Close