2013-11-27 87 views
0

仅尝试通过VBA脚本将数据从5个单元格插入到SQL服务器08数据库的列中。通过VBA脚本从EXCEL脚本中插入多个值到SQL数据库

所以基本上我有1表4列,我想多组数据的插入一次这将数据插入到数据库与下面的结果列..

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 

消息264,级别16,状态1,行 列名 '中间件' 被指定比SET子句中的一次。在同一个SET子句中,列不能分配多个值。修改SET子句以确保列只更新一次。如果SET子句更新视图的列,那么列名称“中间件”可能在视图定义中出现两次。

回答

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并重复其他值? 请相应解释并更新您的答案。

+0

但这将仅仅只有进入TEST6测试1 ...我需要它从Excel工作表中输入多行数据到数据库中。我知道它很简单,但只是让它在我的脑海中变得更加难以实现。 – user3013325

+0

好的,我明白你的意思了,坚持下去。 – NickyvV

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 

代码没有经过测试,但它编译。

+0

欢呼声回应。刚刚尝试过那里的代码(更改为需要等)......仍然收到错误消息“列名'中间件'在SET子句中多次指定” – user3013325

+0

请参阅我的更改。在Update语句中不能指定多个列。我错过了[许可证]。修复了代码。看看是否有效。 –

0

如果您有多行数据,在一次调用存储过程中一次插入所有行会更加高效。要做到这一点,你将数据序列化到XML中,然后调用一个存储过程,该过程将xml作为字符串参数。

AFAIK你不能序列化字典,但你可以序列化一个列表。

所以我建议你循环你的词典(列表词典)填充一个列表适当的值。我倾向于使用结构这一点,但简单的类做工精细,以及,例如:

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 

创建列表并填写如G:

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,否则序列化将不起作用。同样,如果你为类提供你自己的参数构造函数(就像我一样),你还必须提供一个无参数的参数,否则序列化程序会反对。

HTH

附录

什么我忘了,对于VB工作,你需要:

Imports System.IO 
Imports System.Xml.Serialization 
Imports System.Data.SqlClient