MS Access:使用VBA进行SQL插入的日期格式

时间:2016-02-18 00:08:46

标签: vba ms-access ms-access-2013

这可能是一个非常简单的问题,但我很难理解到目前为止我在网上找到的信息。当我尝试从我的VBA中运行SQl时,它在我的strSQl上给出了类型不匹配。

我有一个包含4列的表[tbl_DatabaseUpdateLog]

  

UpdateID(自动编号)

     

开始(日期/时间)

     

结束(日期/时间)

     

持续时间(日期/时间)

我必须定期从公司数据库中提取信息以获得较小的分析项目,并且我想记录运行这些查询所需的频率和时间。每次开始更新时,它都会运行以下命令:

Dim StartUpdate, EndUpdate, LengthUpdate, strSQl As Date
StartUpdate = Time()

Call UpdateAll 'This calls the collection of queries and is irrelevant for my problem

EndUpdate = Time()
LengthUpdate = EndUpdate - StartUpdate
Forms!frm_Timer.Caption = "Update Completed at " & EndUpdate & " (" & Format(LengthUpdate, "HH:MM:SS") & ")"

    DoCmd.SetWarnings (0)
    strSQl = "INSERT INTO tbl_DatabaseUpdateLog ( Start, [End], Duration ) " & _
            "SELECT '" & StartUpdate & "' AS Started, '" & EndUpdate & "' AS Ended, '" & LengthUpdate & "' AS Lasted"
    DoCmd.RunSQL strSQl
    DoCmd.SetWarnings (-1)

DoCmd.Close acForm, Me.Name

我尝试在日期周围使用#并使用Now()而不是Time(),但我觉得我错过了一个基本概念来帮助我解决问题。如果有帮助,我只需要时间和持续时间(而不是日期本身)。

4 个答案:

答案 0 :(得分:3)

  

当我尝试从我的VBA中运行SQl时,它会给我一个类型不匹配   在我的strSQl上

检查这两个陈述......

Dim StartUpdate, EndUpdate, LengthUpdate, strSQl As Date
strSQl = "INSERT INTO tbl_DatabaseUpdateLog ( Start, [End], Duration ) " & _
    "SELECT '" & StartUpdate & "' AS Started, '" & EndUpdate & "' AS Ended, '" & LengthUpdate & "' AS Lasted"

当您声明strSQl As Date时,这意味着strSQl只能保留日期/时间值。一个字符串,如" INSERT INTO ...无论" 不是日期/时间值。因此,当您尝试将此类字符串存储到strSQl时,Access会抱怨数据类型不兼容:"键入不匹配"

由于您希望strSQl保存SQL语句的文本以这种方式声明(而不是As Date):Dim strSQl As String

这种改变应该让你超越错误。为了实现更大的目标,请使用DAO参数查询。

Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim StartUpdate As Date, EndUpdate As Date, LengthUpdate As Date
Dim strSQl As String

StartUpdate = Time()
Call UpdateAll 'This calls the collection of queries and is irrelevant for my problem
EndUpdate = Time()

LengthUpdate = EndUpdate - StartUpdate
Forms!frm_Timer.Caption = "Update Completed at " & EndUpdate & " (" & Format(LengthUpdate, "HH:MM:SS") & ")"

strSQl = "INSERT INTO tbl_DatabaseUpdateLog ([Start], [End], Duration) " & _
    "VALUES ([p1], [p2], [p3]);"
Set db = CurrentDb
Set qdf = db.CreateQueryDef(vbNullString, strSQl)
With qdf
    .Parameters("p1").Value = StartUpdate
    .Parameters("p2").Value = EndUpdate
    .Parameters("p3").Value = LengthUpdate
End With
qdf.Execute dbFailOnError
DoCmd.Close acForm, Me.Name

请注意,对于INSERT的此方法,日期 格式 甚至不是问题。由于StartUpdateEndUpdateLengthUpdate都是有效的日期/时间值,因此您只需将它们提供给参数,而无需考虑格式和#分隔符。

答案 1 :(得分:1)

当简单明了的INSERT INTO SELECT FROM (literal)更简单时,我发现你正在使用INSERT INTO (columns) VALUES (values)。您还可以在单​​个VALUES语句中包含多个INSERT子语句,这是完整的。

我也看到你存储了非规范化数据,很明显Duration可以从End - Start派生,所以你可能想要删除该列。

另外,请避免匈牙利表示法,在这种情况下,使用tbl_为表格添加前缀。它不再是20世纪80年代了。不要这样做。

使用字符串连接的简短而简单的答案:

从不这样做

SQL Server

如果您使用的是SQL Server,则需要将日期括在单引号中,并且需要转换为明确的日期格式字符串,例如yyyy-MM-dd HH:mm:ss

strSQL = "INSERT INTO neverDoThis VALUES ( '" & Format( startUpdate, "yyyy-MM-dd HH:mm:ss" & "' )"

Access / Jet

如果你正在使用Access或Jet,你需要用哈希字符'#'括起日期并使用'MM / dd / yyyy hh:mm:ss tt'格式(愚蠢的美国人......)。

strSQL = "INSERT INTO neverDoThis VALUES ( #" & Format( startUpdate, "MM/dd/yyyy hh:mm:ss tt" & "# )"

以下是Format功能的参考:https://msdn.microsoft.com/en-us/library/office/gg251755.aspx?f=255&MSPPError=-2147217396

更好的答案:使用参数

改为

SQL Server

SQL Server使用@foo等命名参数:

cmd.CommandText = "INSERT INTO databaseUpdateLog ( [Start], [End], [Duration] ) VALUES ( @start, @end, @duration )"
cmd.Parameters.Append cmd.CreateParameter( "@start", , , startUpdate )
cmd.Parameters.Append cmd.CreateParameter( "@end", , , endUpdate )
cmd.Parameters.Append cmd.CreateParameter( "@duration", , , lengthUpdate )

Access / Jet

Access使用按添加顺序访问的匿名占位符,使用“?”:

cmd.CommandText = "INSERT INTO databaseUpdateLog ( [Start], [End], [Duration] ) VALUES ( ?, ?, ? )"
cmd.Parameters.Append cmd.CreateParameter( "?", , , startUpdate )
cmd.Parameters.Append cmd.CreateParameter( "?", , , endUpdate )
cmd.Parameters.Append cmd.CreateParameter( "?", , , lengthUpdate )

VBA中的Append方法是Sub,因此调用它不使用括号。
CreateParameter方法在中间有3个可选参数:TypeDirectionSize,可以从值中推断出来,因此通过放置{{1 }}

答案 2 :(得分:1)

更直接的方法是使用原生DAO:

Dim rs As DAO.Recordset
Dim StartUpdate As Date
Dim EndUpdate As Date
Dim LengthUpdate As Date

StartUpdate = Time    
Call UpdateAll 'This calls the collection of queries and is irrelevant for my problem.    
EndUpdate = Time
LengthUpdate = EndUpdate - StartUpdate
Forms!frm_Timer.Caption = "Update Completed at " & EndUpdate & " (" & Format(LengthUpdate, "h:mm:ss") & ")"

Set rs = CurrentDb.OpenRecordset("Select Top 1 * From tbl_DatabaseUpdateLog")
rs.AddNew
    rs!Start.Value = StartUpdate
    rs!End.Value = EndUpdate
    rs!Duration.Value = LengthUpdate
rs.Update
rs.Close    
Set rs = Nothing

DoCmd.Close acForm, Me.Name

答案 3 :(得分:-1)

要计算的时间,在VBA中您可以使用以下表达式:

CDate(Now - Date())

将结果包含在#中,因为结果仍然是日期类型,即使只存储了时间信息。

您可以使用DateDiff函数计算持续时间,您需要选择合适的单位。例如:

DateDiff(DateInterval.Second, EndUpdate, StartUpdate)

结果是一个长整数,因此您不需要将结果括在SQL中。

推荐使用BTW参数化SQL,但不是必需的。