简体   繁体   English

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

[英]How to use variables in SQL insert statement directly

I have a SQL statement:我有一个 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 &"')"

I want to use this variable "V2" in the value into SQL statement but without using the quotes symbol.我想在 SQL 语句中的值中使用这个变量“V2”,但不使用引号。

Like:喜欢:

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

How can I set the "V2" variable correctly to be like that?如何将“V2”变量正确设置为这样?

You need to use something like this:你需要使用这样的东西:

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

This question really is a duplicate of other questions ( here and here for example), since many newcomers to Access both expect and want to be able to reference VBA variables directly from within SQL statements.这个问题确实是其他问题的重复(例如此处此处),因为许多 Access 新手都希望并希望能够直接从 SQL 语句中引用 VBA 变量。 It is essentially the same issue no matter if it's an INSERT, UPDATE, SELECT, etc.无论是 INSERT、UPDATE、SELECT 等,本质上都是相同的问题。

Almost all good answers eventually lead to parameterized QueryDefs or ADO command, and I agree that this is the best-practice approach for various reasons.几乎所有好的答案最终都会导致参数化的 QueryDefs 或 ADO 命令,我同意这是出于各种原因的最佳实践方法。 But very few comments and answers address the issue directly, so here's a different sort of answer ...但是很少有评论和答案直接解决这个问题,所以这里有一个不同的答案......

Access SQL cannot directly reference VBA module variables. Access SQL 不能直接引用 VBA 模块变量。 However, there a couple alternatives that can work, but they have their own drawbacks.但是,有几种替代方法可以工作,但它们都有自己的缺点。

  • Access SQL can directly reference public functions declared in VBA modules. Access SQL可以直接引用 VBA 模块中声明的公共函数。 Because a VBA functions can essentially access any other variable or object and return a value, it can certainly return a variable's value that is otherwise not directly accessible to SQL.因为 VBA 函数本质上可以访问任何其他变量或对象并返回一个值,所以它当然可以返回一个变量的值,否则 SQL 不能直接访问该值。
    • The most critical issue to realize here is that context in which such a function is called must be assured before the query is executed.这里要意识到的最关键的问题是在执行查询之前必须确保调用此类函数的上下文。 If a query which references such a function is ever called "out of order" (when the variable is not properly initialized), then it will of course result in expected behavior and/or invalid data.如果引用此类函数的查询被称为“乱序”(当变量未正确初始化时),那么它当然会导致预期行为和/或无效数据。

'* 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())
  • A special object that can be accessed is called TempVars (docs here ).可以访问的特殊对象称为TempVars此处文档)。 It really was designed to be used with macros, but Access exposes it as an object directly accessible from within an SQL statement, so it is technically allowed.它确实是为与宏一起使用而设计的,但 Access 将其公开为可从 SQL 语句中直接访问的对象,因此在技术上是允许的。
    • The biggest drawback is that the values are stored as VBA variants, and SQL does not always interpret them correctly.最大的缺点是值存储为 VBA 变体,并且 SQL 并不总是正确解释它们。 Using explicit conversion functions can resolve this.使用显式转换函数可以解决这个问题。 The example demonstrates this by wrapping the TempVars reference in CDbl() .该示例通过在CDbl()包装TempVars引用来演示这一点。

'* 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))

I just started using Access, and found the accepted answer to be very helpful.我刚开始使用 Access,发现接受的答案非常有帮助。 Thank you, @Pablo Santa Cruz.谢谢你,@Pablo Santa Cruz。

I was looking for an explanation that would help eliminate SQL injection in my code.我一直在寻找有助于消除代码中 SQL 注入的解释。 When I implemented this code, I ran into problems with unset values in the parameters.当我实现这段代码时,我遇到了参数中未设置值的问题。 I changed my references to use indexes, Parameters(0), etc., and then had datatype mismatches, as I had declared all of my parameters as strings.我更改了我的引用以使用索引、Parameters(0) 等,然后数据类型不匹配,因为我已将所有参数声明为字符串。

When I traced the process, I saw that when assigning the INSERT statement to cmd.CommandText, parameters were automatically added, matching the meta data from the database.追查过程发现,在将INSERT语句赋值给cmd.CommandText的时候,自动添加了参数,与数据库中的元数据相匹配。 So, parameters 2 and 3 had to be changed to match the parameters declared types, of integer and datetime, respectively.因此,必须更改参数 2 和 3 以分别匹配声明类型的整数和日期时间参数。

Kinda cool, maybe a little creepy.有点酷,也许有点令人毛骨悚然。 Here's my example:这是我的例子:

' 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM