尝试通过VBA脚本将5个单元格中的数据插入到SQL Server 08数据库的列中。
所以基本上我有1个包含4列的表,我想一次将多组数据插入到列中,这会将数据插入到DB中,结果如下。
Server Name Middleware Version License
TEST6 Testing 1 1
TEST6 Testing1 1 1
TEST6 Testing2 1 1
TEST6 Testing3 1 1
我知道下面的代码中的值不正确,但是当执行VBA脚本时,我收到错误消息(在vba代码下面)。
Dim val1 As String, val2 As String, val3 As String, val4 As String
val1 = Range("B126").Value
val2 = Range("C126").Value
val3 = Range("C127").Value
val4 = Range("D126").Value
conn.Open sConnString
Dim item As String
item4 = "INSERT INTO [IndustrialComp].[dbo].[Middleware]("
item4 = item4 & " [server_name],[middleware],[middlware],[version]"
item4 = item4 & " )Values("
item4 = item4 & " '" & val1 & "', '" & val2 & "', '" & val3 & "','" & val4 & "')"
conn.Execute item4
End Sub
Msg 264,Level 16,State 1,Line 1 在SET子句中多次指定列名“middleware”。在同一SET子句中不能为列分配多个值。修改SET子句以确保列只更新一次。如果SET子句更新视图的列,则列名“middleware”可能在视图定义中出现两次。
答案 0 :(得分:1)
我相信您在INSERT语句中指定的列是重复的,因此不正确。 尝试:
item4 = item4 & " [server_name],[middleware],[version],[license]"
更新: 您的SQL语句应如下所示:
INSERT INTO [IndustrialComp].[dbo].[Middleware]([server_name],[middleware],[version],[license])
VALUES ('TEST6','Testing',1,1)
,('TEST6','Testing1',1,1)
,('TEST6','Testing2',1,1)
,('TEST6','Testing3',1,1)
因此,您必须在要插入的每一行的括号之间重复该块。
然而,您现在只有4个变量在您的解决方案中包含4个不同的值,因此您永远无法插入这4个不同的行,因为您只选择单元格B126,C126中的值, C127和D126。这可能是您要插入的第一行?或者您想自己添加1,2,3到Testing
并重复其他值?
请相应地解释和更新您的答案。
答案 1 :(得分:0)
我假设数据在Excel中。如果是这样,只需循环遍历行。此外,您的val1,val2等似乎与该示例不匹配。也许你的意思是val3是D126而val4是E126。我会假设的。这是更正后的代码:
Dim sSQL as string
Dim i as long
i=0
while ActiveSheet.Range("B126").offset(i,0).value <> "" 'stop when there is a blank cell
i=i+1
conn.Open sConnString
sSQL = "INSERT INTO [IndustrialComp].[dbo].[Middleware]("
sSQL = sSQL & " [server_name],[middleware],[version],[license]"
sSQL = sSQL & " )Values ("
sSQL = sSQL & " '" & ActiveSheet.Range("B126").offset(i,0).Value & "', "
sSQL = sSQL & " '" & ActiveSheet.Range("C126").offset(i,0).Value & "', "
sSQL = sSQL & " '" & ActiveSheet.Range("D126").offset(i,0).Value & "', "
sSQL = sSQL & " '" & ActiveSheet.Range("E126").offset(i,0).Value & "' "
sSQL = sSQL & ")"
conn.Execute sSQL
wend
代码未经测试但已编译。
答案 2 :(得分:0)
如果您有多行数据,则在一次调用存储过程中一次性插入所有行会更有效。为此,您将数据序列化为xml,然后调用存储过程,该过程将xml作为字符串参数。
AFAIK您无法序列化词典,但您可以序列化列表。
因此,我建议您循环填充具有适当值的List的Dictionary(词典列表)。我倾向于使用Structures,但简单的类也可以正常工作,例如:
Public Class DBData
Public pKey As Integer
Public pValue As Double
Public Sub New(key As Integer, val As Double)
pKey = key
pValue = val
End Sub
Public Sub New()
pKey = 0
pValue = 0.0
End Sub
End Class
创建您的列表并填写它,例如:
Dim myList As New List(Of DBData)
For Each kvPair In dict
myList.Add(New DBData(kvPair.Key, kvPair.Value))
Next
现在有点神奇的序列化:
Dim sw As New StringWriter
Dim serializer As New XmlSerializer(GetType(List(Of DBData)))
Dim ns As New XmlSerializerNamespaces()
serializer.Serialize(sw, myList)
Dim xml As String
xml = sw.ToString
Dim pos As Integer
pos = xml.IndexOf("<Array")
xml = xml.Substring(pos)
请注意,我正在剥离刚刚创建的xml的标头。这是因为如果包含标题,我从来没有能够使SQL Server工作 - 你可能可以,我只是看起来不够努力。
我们像这样调用存储过程(显然将连接字符串更改为适合您的存储过程):
Using conn As New SqlConnection("Integrated Security=true; Initial Catalog=dbname; Data Source=servername")
Using cmd As New SqlCommand("uspDBDataInsert", conn)
cmd.CommandType = CommandType.StoredProcedure
Dim param As SqlParameter
param = cmd.CreateParameter
param.ParameterName = "@dbdata"
param.DbType = DbType.String
param.Value = xml
cmd.Parameters.Add(param)
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Using
End Using
对于SQL Server,所需的过程如下所示:
CREATE PROCEDURE [dbo].[uspDBDataInsert]
-- Add the parameters for the stored procedure here
@dbdata varchar(MAX)
AS
BEGIN try
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @idoc int
--Create an internal representation of the XML document
EXEC sp_xml_preparedocument @idoc OUTPUT, @dbdata
insert into DBData
(
id, rowvalue
)
select
pKey,pValue
FROM OPENXML (@idoc, '/ArrayOfDBData/DBData',2)
WITH (
pKey int,
pValue float
)
select @@ROWCOUNT
end try
begin catch
declare @msg nvarchar(200)
SELECT @msg = ('Error during insert of DBData...')
end catch
显然,你需要将ArrayOf更改为你所谓的课程,当然还要使用自己的表格。
虽然我在这里只显示了一个简单的键/值对,但您可以用完全相同的方式填充多列表。
需要注意的一点是:您的类/结构在Public模块中必须是Public,否则serialize将不起作用。此外,如果您为类提供自己的参数构造函数(就像我一样),您还必须提供无参数构造函数,否则序列化程序将再次对象。
HTH
附录
我忘记了,为了让VB工作,你需要:
Imports System.IO
Imports System.Xml.Serialization
Imports System.Data.SqlClient