VBA 中 DateAdd 的 MS Access 问题插入日期格式不一致的语句

MS Access Problem with DateAdd in VBA Insert statement with inconsistent date format

我对如何在我的数据库中存储日期有疑问。

我需要创建一个临时 TableC,其中将为 TableA 上的每条记录插入 X 条记录。其中 X 是周数。结果 table 将在 UNION 语句中与其他几个查询一起使用。

问题在于 DateAdd 如何为每条新记录创建日期。日期最初以 dd/mm/yyyy 格式存储。但是生成的 DateAdd("ww", i, rst![Date]) 有时会以 mm/dd/yyyy 格式存储,从而在 30K 结果行中造成严重破坏。

写了一个 VB Sub 来创建 table,下面是一个关于实际存储方式与预期存储方式的示例。

 

Sub AddItems()
    Dim db as DAO.Database
    Dim rst as DAO.Recordset
    Dim Sql1, Sql2 as String

    Sql1 = "SELECT [a].*, [b].[Date], [b].[Weeks]. [b].[Rate] FROM TableA as [a] LEFT JOIN TableB as [b] WHERE [a].[GroupId] = [b].[Id] ORDER BY [b].[Date], [a].[Id];"

    Set db = CurrentDb
    Set rst = db.OpenRecordset(Sql1)

    rst.movefirst
    While NOT rst.EOF
        If rst![Weeks] > 0 Then
            For i = 1 to rst![Weeks]
                Sql2 = "INSERT INTO TableC ([ID], [CUSTOMER], [DATE], [AMOUNT]) VALUES ("
                Sql2 = Sql2 & rst![ID] & ", " & rst![CUSTOMER]
                Sql2 = Sql2 & "#" & Format(DateAdd("ww", (i - 1), Format(rst![Date], "mm/dd/yyyy")), "mm/dd/yyyy") & "#"
                Sql2 = Sql2 & ", " & rst![AMOUNT]
                Sql2 = Sql2 & ")"
                Debug.Print Format(DateAdd("ww", (i - 1), Format(rst![Date], "mm/dd/yyyy")), "mm/dd/yyyy")
                db.Execute(Sql2)
            Next i
        End If
        rst.movenext
    Wend
End Sub  

结果 TABLE 样本 +------------+------------+------------+ |星期 |关于 Table |在调试 |预期数据已插入 +------------+------------+------------+ | 1 | 12/02/2019 | 2019 年 2 月 12 日 |应该是 2/12/2019 | |作为 2 月 12 日 |正确 | +------------+------------+------------+ | 2 | 2019 年 12 月 9 日 | 2019 年 9 月 12 日 |应该是 2019 年 12 月 9 日 | |作为 9 月 12 日 |正确 | +------------+------------+------------+ | 3 | 16/12/2019 | 16/12/2019 |应该是 2019 年 12 月 16 日 | |正确 |正确 | +------------+------------+------------+

立即 Window 上打印的结果是正确的,但实际 table 上的信息不正确。我的样本数据从 02/12/2019 开始(2/12/2019 已通过 TableA 中 table 视图中的日期选择器确认)

调试 window 显示要存储的正确信息,但 table 上的信息不正确,尽管 TableC 中的字段 [DATE] 的格式为 "Short Date" 并使用 IsDate 验证规则。

如果没有这两个 Format 语句,结果将与预期的结果大相径庭。然而,生成的 DATE 字段并不一致。

有没有办法根据系统设置一致地生成日期并存储它们?

如果数据类型为日期,则日期值不会以某种格式存储。一种格式仅供显示或在 SQL 中连接时使用。所以尝试:

Sub AddItems()

    Dim db  As DAO.Database
    Dim rst As DAO.Recordset
    Dim Sql1 As String
    Dim Sql2 As String

    Sql1 = "SELECT [a].*, [b].[Date], [b].[Weeks]. [b].[Rate] FROM TableA as [a] LEFT JOIN TableB as [b] WHERE [a].[GroupId] = [b].[Id] ORDER BY [b].[Date], [a].[Id];"

    Set db = CurrentDb
    Set rst = db.OpenRecordset(Sql1)

    rst.MoveFirst
    While Not rst.EOF
        If rst![Weeks] > 0 Then
            For i = 1 to rst![Weeks]
                Sql2 = "INSERT INTO TableC ([ID], [CUSTOMER], [DATE], [AMOUNT]) VALUES ("
                Sql2 = Sql2 & rst![ID] & ", '" & rst![CUSTOMER] & "', "
                Sql2 = Sql2 & "#" & Format(DateAdd("ww", i - 1, rst![Date]), "mm/dd/yyyy") & "#, "
                Sql2 = Sql2 & Str(rst![AMOUNT])
                Sql2 = Sql2 & ")"
                Debug.Print Format(DateAdd("ww", i - 1, rst![Date]), "mm/dd/yyyy")
                db.Execute(Sql2)
            Next i
        End If
        rst.MoveNext
    Wend
End Sub  

也就是说,为 TableC 打开第二个记录集然后使用 AddNewUpdate 追加会更简单、更快周的记录。

如果您的“日期”存储为 文本,除了手动编辑以使其格式一致之外,没有办法解决您的问题。

先说几点:

  • 根本没有声明变量 i,您应该在模块的 header 中使用 Option Explicit 以使 VBE 能够警告您。
  • Date是保留字,所以我改名为YourDate.
  • 变量 sql1 被隐式定义为类型变体。
  • 您对变量 sql1 的 SQL 的定义在句法上不正确。我更正了它,希望这是你的意思。
  • 我希望您的 table 字段 YourDate 是日期类型而不是字符串类型。如果它是字符串,那么您需要先在代码中将其转换为日期,或者在 table.
  • 中更好
  • 如果您隐含地想使用它来清除您所做的事情,请始终明确使用 属性 Value,并且不要意外分配 object。
  • 在 SQL 注入的情况下,连接 SQL 字符串是不安全的。面向 object 的方法不是,它是类型安全的。

这应该会如您所愿:

Option Compare Database
Option Explicit

Sub AddItems()
    Dim sql1 As String
    sql1 = "SELECT a.*, b.YourDate, b.Weeks, b.Rate FROM TableA as a LEFT JOIN TableB as b On a.GroupId = b.Id ORDER BY b.YourDate, a.Id"

    Dim db As DAO.Database
    Set db = CurrentDb

    Dim rst As DAO.Recordset
    Set rst = db.OpenRecordset(sql1)

    rst.MoveFirst
    While Not rst.EOF
        If rst("Weeks").Value > 0 Then
            Dim i As Long
            For i = 1 To rst("Weeks").Value
                With CurrentDb().CreateQueryDef(vbNullString, _
                    "INSERT INTO TableC ([ID], [CUSTOMER], [YourDATE], [AMOUNT]) " & _
                    "VALUES (@ParID, @ParCustomer, @ParDate, @ParAmount)")
                    .Parameters("@ParID").Value = rst("ID").Value
                    .Parameters("@ParCustomer").Value = rst("CUSTOMER").Value
                    .Parameters("@ParDate").Value = DateAdd("ww", (i - 1), rst("YourDate").Value)
                    .Parameters("@ParAmount").Value = rst("AMOUNT").Value
                    .Execute dbFailOnError
                End With
            Next i
        End If
        rst.MoveNext
    Wend

    rst.Close
End Sub