这可能是一个非常简单的问题,但我很难理解到目前为止我在网上找到的信息。当我尝试从我的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(),但我觉得我错过了一个基本概念来帮助我解决问题。如果有帮助,我只需要时间和持续时间(而不是日期本身)。
答案 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
的此方法,日期 格式 甚至不是问题。由于StartUpdate
,EndUpdate
和LengthUpdate
都是有效的日期/时间值,因此您只需将它们提供给参数,而无需考虑格式和#
分隔符。
答案 1 :(得分:1)
当简单明了的INSERT INTO SELECT FROM (literal)
更简单时,我发现你正在使用INSERT INTO (columns) VALUES (values)
。您还可以在单个VALUES
语句中包含多个INSERT
子语句,这是完整的。
我也看到你存储了非规范化数据,很明显Duration
可以从End - Start
派生,所以你可能想要删除该列。
另外,请避免匈牙利表示法,在这种情况下,使用tbl_
为表格添加前缀。它不再是20世纪80年代了。不要这样做。
(从不这样做)
如果您使用的是SQL Server,则需要将日期括在单引号中,并且需要转换为明确的日期格式字符串,例如yyyy-MM-dd HH:mm:ss
。
strSQL = "INSERT INTO neverDoThis VALUES ( '" & Format( startUpdate, "yyyy-MM-dd HH:mm:ss" & "' )"
如果你正在使用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使用@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使用按添加顺序访问的匿名占位符,使用“?”:
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个可选参数:Type
,Direction
和Size
,可以从值中推断出来,因此通过放置{{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,但不是必需的。