使用VBA(Excel)将数据传输到SQL Server但避免重复的列?

时间:2019-06-14 11:39:48

标签: sql sql-server excel vba

我的主要目标是在使用vba时将一些数据从excel传输到SQL Server,但是在此过程中,我希望检测并避免传输一些重复的月份列。

这是我到目前为止所拥有的:

$ArrayToOrder=Array
(
    [0] => Array
        (
            [Field_1] => 13
            [Field_2] => 15
            [Field_3] => 3 //(Arthur)
        )

    [1] => Array
        (
            [Field_1] => 121
            [Field_2] => 20
            [Field_3] => 11 //(Bruce)                  
        )

    [2] => Array
        (
            [Field_1] => 25
            [Field_2] => 17
            [Field_3] => 2 //(Mary)
        )
)   

并且将返回类似:

Sub UploadExcelToSQL()

Dim adoCN As ADODB.Connection
Dim sConnString As String
Dim sSQL As String
Dim lRow As Long, lCol As Long

sConnString = "Provider=SQLOLEDB;Data Source=agrsql004\instance01;Initial Catalog=DEHL;Integrated Security=SSPI"

Set adoCN = CreateObject("ADODB.Connection")

adoCN.Open sConnString


For lRow = 2 To 4

     sSQL = "INSERT INTO dbo.MonthlyValue (ID, Year, Month, Value) " & _
            " VALUES (" & _
            "'" & Sheet2.Cells(lRow, 1) & "', " & _
            "'" & Sheet2.Cells(lRow, 2) & "', " & _
            "'" & Sheet2.Cells(lRow, 3) & "', " & _
            "'" & Sheet2.Cells(lRow, 4) & "')"

    adoCN.Execute sSQL

Next lRow

adoCN.Close

Set adoCN = Nothing

End Sub

我想要的是这样的东西:

ID  Year Month Value
123 2018   1   9987
123 2018   2   80988
123 2018   1   8990

总而言之,我希望代码能够检测到同年的重复月份,并避免将其转移到SQL Server中的数据库,这样一个ID在x年的每个月只能有一个值。 我在这方面的知识还很有限,因此不胜感激。

1 个答案:

答案 0 :(得分:0)

一种解决方案是针对表的三个列IDYearMonth的组合创建一个唯一约束

Alter Table dbo.MonthlyValue 
    Add Constraint MonthlyValueUniqueContraint  UNIQUE (ID, Year, Month)

注意 ,如果数据库中已经存在重复项,则无法创建约束-在这种情况下,您必须先清理数据。

这意味着您可以有多个具有相同ID,同一年或同一月的记录,甚至可以有多个具有相同ID和同一年(但不同月份)或相同ID和月(但不同)的记录年)。仅ID,年份和月份的组合是唯一的。

当您尝试插入已经存在的组合时(例如,像第三行一样),adoCN.Execute将引发错误-您必须在程序中捕获该错误,然后它才能继续。请注意,以下代码将忽略 any 错误,如果您想要一个可靠的解决方案,则应检查错误代码,并仅在出现唯一约束错误时才继续操作(例如,不行)。错误,因为连接中断或可能发生的数千个其他错误之一。

On Error Resume Next
adoCN.Execute sSQL
If Err.Number <> 0 Then Debug.Print Err.Number, Err.Description  
On Error GoTo 0

当然,一种替代方法总是可以检查数据库中是否已存在该记录。
缺点是每行需要两次到数据库的往返,优点是如果要保留第二个而不是第一个值,则可以实现Update语句。或者,您可以编写一个小的存储过程,以便在数据库端执行逻辑-但我认为这导致了目前的发展。

无论如何,您应该设置约束-让数据库监视您的数据保持干净。