在 MS-Access 中生成 INSERT INTO 语句
Generate INSERT INTO statements in MS-Access
我喜欢将数据(单条记录)从一个 Access 数据库导出到另一个国家的另一个数据库。我的想法是,我想在每封电子邮件中发送一个包含 INSERT INTO 语句的文本文件,接收 PC 只执行这些 INSERT INTO 语句。我已经编写了读取和执行这些文本文件中的 INSERT INTO 语句的代码。
显然我必须生成 INSERT INTO 语句。
这是一个例子。
我有以下 table:
Table1
Id number
PersonName text
DoB date, can be empty
NumberOfChildern number, can be empty
我select这样的数据:
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 中编写代码,分析 table 和我要导出的记录以检查使用了哪种字段(即日期),然后生成上述语句.
我确定我可以做到这一点,但我想知道以前是否有人这样做过。
我不想重新发明轮子。
但是搜索 "generate SQL insert statements" 并不是很有效。
有什么想法吗?
今天是你的幸运日。我已经为 SQL 服务器完成了此操作 - 在下面进行了一些修改后它应该适用于 Access SQL.
关键是插入 VALUES NULL,如果值为空则不创建不同的语句。
Access 可能不需要 SET IDENTITY_INSERT ON/OFF
。
Gustav 发布了一个 可以替代所有 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
'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
我喜欢将数据(单条记录)从一个 Access 数据库导出到另一个国家的另一个数据库。我的想法是,我想在每封电子邮件中发送一个包含 INSERT INTO 语句的文本文件,接收 PC 只执行这些 INSERT INTO 语句。我已经编写了读取和执行这些文本文件中的 INSERT INTO 语句的代码。
显然我必须生成 INSERT INTO 语句。
这是一个例子。
我有以下 table:
Table1
Id number
PersonName text
DoB date, can be empty
NumberOfChildern number, can be empty
我select这样的数据:
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 中编写代码,分析 table 和我要导出的记录以检查使用了哪种字段(即日期),然后生成上述语句. 我确定我可以做到这一点,但我想知道以前是否有人这样做过。 我不想重新发明轮子。 但是搜索 "generate SQL insert statements" 并不是很有效。
有什么想法吗?
今天是你的幸运日。我已经为 SQL 服务器完成了此操作 - 在下面进行了一些修改后它应该适用于 Access SQL.
关键是插入 VALUES NULL,如果值为空则不创建不同的语句。
Access 可能不需要 SET IDENTITY_INSERT ON/OFF
。
Gustav 发布了一个
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
'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