在 MS-Access 中生成 INSERT INTO 语句

Posted

技术标签:

【中文标题】在 MS-Access 中生成 INSERT INTO 语句【英文标题】:Generate INSERT INTO statements in MS-Access 【发布时间】:2016-10-19 09:54:51 【问题描述】:

我喜欢将数据(单个记录)从一个 Access 数据库导出到另一个国家的另一个数据库。我的想法是我想在每封电子邮件中发送一个带有 INSERT INTO 语句的文本文件,而接收 PC 只执行这些 INSERT INTO 语句。我已经编写了代码来读取和执行这些文本文件中的 INSERT INTO 语句。

显然我必须生成 INSERT INTO 语句。

这是一个例子。

我有下表:

Table1
Id                number
PersonName        text
DoB               date, can be empty
NumberOfChildern  number, can be empty

我选择这样的数据:

SELECT Id, PersonName, DoB, NumberOfChildern FROM Table1;

我想要生成的是这样的语句:

INSERT INTO Table1 (Id, PersonName, DoB, NumberOfChildern ) VALUES (1, ‘Peter’, #5-17-1990#, 1)

如果始终填写所有字段,那么我可以编写一次代码,仅此而已。但是,如果几个字段可能包含数据或可能没有数据,则会出现问题。

以下是上述声明的一些相似但不同的版本:

INSERT INTO Table1 (Id, PersonName, DoB, NumberOfChildern ) VALUES (1, ‘Peter’, #5-17-1990#, 1)
INSERT INTO Table1 (Id, PersonName, NumberOfChildern ) VALUES (1, ‘Peter’, 1)
INSERT INTO Table1 (Id, PersonName, DoB ) VALUES (1, ‘Peter’, #5-17-1990#)
INSERT INTO Table1 (Id, PersonName ) VALUES (1, ‘Peter’)

只有两个可以包含 NULL 值的字段,这个语句已经有 4 个不同的版本,并且随着字段的增多,它变得越来越复杂(不是很复杂,但需要更多的工作)。

我考虑在 VBA 中编写代码来分析我要导出的表和记录,以检查使用了哪种字段(即日期),然后生成类似上面的语句。 我确信我可以做到这一点,但我想知道是否其他人以前也这样做过。 我不想重新发明***。 但是搜索“生成 SQL 插入语句”并不是很有效。

有什么想法吗?

【问题讨论】:

【参考方案1】:

今天是你的幸运日。我已经为 SQL Server 完成了这个 - 在下面进行了一些修改,它应该适用于 Access SQL。

关键是插入VALUES NULL,如果值为null,则不要创建不同的语句。

Access 可能不需要SET IDENTITY_INSERT ON/OFF

Gustav 发布了一个generic function,可以替换所有的Sqlify/SqlDate 等辅助函数,涵盖更多的数据类型。

Public Sub InsertStatementsSql(ByVal sTABLE As String)

    Dim DB As DAO.Database
    Dim TD As DAO.TableDef
    Dim RS As DAO.Recordset
    Dim fld As DAO.Field
    Dim sKpl As String
    Dim sStart As String
    Dim sValues As String
    Dim S As String
    Dim v As Variant
    Dim i As Long
    Dim bIdentity As Boolean

    Set DB = CurrentDb
    Set TD = DB.TableDefs(sTABLE)
    Set RS = DB.OpenRecordset(sTABLE, dbOpenSnapshot)


    ' Check for Autonumber/IDENTITY column
    bIdentity = False
    For i = 0 To TD.Fields.count - 1
        If (TD.Fields(i).Attributes And dbAutoIncrField) > 0 Then
            bIdentity = True
            Exit For
        End If
    Next i

    If bIdentity Then
        sKpl = sKpl & "SET IDENTITY_INSERT " & sTABLE & " ON;" & vbCrLf & vbCrLf
    End If

    ' "INSERT INTO ... VALUES " for every line
    For i = 0 To TD.Fields.count - 1
        sStart = StrAppend(sStart, TD.Fields(i).Name, ", ")
    Next i
    sStart = "INSERT INTO " & sTABLE & " (" & sStart & ") VALUES "

    ' One line per record
    Do While Not RS.EOF
        sValues = ""
        For i = 0 To TD.Fields.count - 1
            v = RS(i)
            If IsNull(v) Then
                S = "NULL"
            Else
                Set fld = TD.Fields(i)
                Select Case fld.Type
                    Case dbText, dbMemo: S = Sqlify(CStr(v))
                    Case dbDate: S = SqlDate(CDate(v))
                    Case dbDouble, dbSingle: S = SqlNumber(CDbl(v))
                    Case Else: S = CStr(v)
                End Select
            End If
            sValues = StrAppend(sValues, S, ", ")
        Next i
        ' Append line to full SQL
        sKpl = sKpl & vbCrLf & sStart & " (" & sValues & ");"
        RS.MoveNext
    Loop
    RS.Close
    Set TD = Nothing

    If bIdentity Then
        sKpl = sKpl & vbCrLf & vbCrLf & "SET IDENTITY_INSERT " & sTABLE & " OFF;" & vbCrLf
    End If

    Debug.Print sKpl

    ' see https://support.microsoft.com/en-us/kb/210216 or https://msdn.microsoft.com/en-us/library/office/ff192913.aspx
    ' or https://***.com/a/25431633/3820271
    'ClipBoard_SetData sKpl

End Sub

' ------------------- helper functions -----------------

'  ein'string --> 'ein''string'
Public Function Sqlify(ByVal S As String) As String

    S = Replace(S, "'", "''")
    S = "'" & S & "'"
    Sqlify = S

End Function

Public Function SqlDate(vDate As Date) As String
    SqlDate = "#" & Format(vDate, "yyyy-mm-dd") & "#"
End Function

Public Function SqlNumber(num As Double) As String
    SqlNumber = Replace(CStr(num), ",", ".")
End Function

Public Function StrAppend(sBase As String, sAppend As Variant, sSeparator As String) As String

    If Len(sAppend) > 0 Then
        If sBase = "" Then
            StrAppend = Nz(sAppend, "")
        Else
            StrAppend = sBase & sSeparator & Nz(sAppend, "")
        End If
    Else
        StrAppend = sBase
    End If

End Function

【讨论】:

哇!这是我的幸运日。我刚刚尝试复制并粘贴了创建的带有 NULL 值的 SQL 语句,它工作正常。这是我插入的“INSERT INTO Table1 (Id, PersonName, DoB, NumberOfChildern) VALUES (3, 'Edgar', NULL, NULL);"

以上是关于在 MS-Access 中生成 INSERT INTO 语句的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle SQL Developer 中生成带有子查询的 INSERT 语句?

VB.net:INSERT INTO 查询在 Access 数据库中生成所有“-1”

ms-access:仅显示特定日期内记录的报告

在动作方法中生成输出URL (Generating Outgoing URLs in Action Methods) |

“INSERT INTO 中的语法错误”ms-access vb.net [重复]

将一个文件中的内容,在另一个文件中生成. for line in f1, f2.write(line)