【问题标题】:VB.Net - Insert .CSV file records after checking for duplicatesVB.Net - 检查重复后插入 .CSV 文件记录
【发布时间】:2015-07-24 16:23:13
【问题描述】:

我需要监控一个目录中的多个文件夹,并在每个文件夹中插入来自多个 .csv 文件的记录。我已经使用 filesystemwatcher 进行监控。现在我需要检查每个更新/新创建的 .csv 文件中的记录并将其插入 SQL Server 数据库。我不能有唯一的字段,因为可能有可以重复的字段值。所以我使用三个字段的组合来检查重复并仅当数据库中不存在 .csv 文件记录时才插入它。下面的代码在 cmdInsertSQL.ExecuteNonQuery() 行上抛出错误:

参数化查询“(@ColumnA int,@ColumnB datetime,@ColumnC time(7),@ColumnD varcha”需要参数“@ColumnA”,但未提供该参数。

下面是代码:

Private Sub ReadAndInsertCSVData()
Dim table As New DataTable()
table.Columns.Add("ColumnA")
table.Columns.Add("ColumnB")
table.Columns.Add("ColumnC")
table.Columns.Add("ColumnD")
table.Columns.Add("ColumnE")
table.Columns.Add("ColumnF")
table.Columns.Add("ColumnG")
table.Columns.Add("ColumnH")
table.Columns.Add("ColumnI")
table.Columns.Add("ColumnJ")
table.Columns.Add("ColumnK")
table.Columns.Add("ColumnL")
table.Columns.Add("ColumnM")
table.Columns.Add("ColumnN")
table.Columns.Add("ColumnO")
table.Columns.Add("ColumnP")
table.Columns.Add("ColumnQ")
table.Columns.Add("ColumnR")
table.Columns.Add("ColumnS")
table.Columns.Add("ColumnT")
table.Columns.Add("ColumnU")
table.Columns.Add("ColumnV")
table.Columns.Add("ColumnW")
table.Columns.Add("MetNo")
Dim parser As New FileIO.TextFieldParser("C:\Folder1\SD08.CSV")
parser.Delimiters = New String() {","}
parser.HasFieldsEnclosedInQuotes = True
parser.TrimWhiteSpace = True
Do Until parser.EndOfData = True
    table.Rows.Add(parser.ReadFields())
Loop
For Each row As DataRow In table.Rows
    row("MetNo") = lblMetNo.Text
Next
Dim strSQLConnectionString As String = "Data Source=ServerName;Initial Catalog=DBName;Integrated Security=SSPI;"
Dim connTemp As New SqlClient.SqlConnection(strSQLConnectionString)
Dim connInsertSQL As New SqlClient.SqlConnection(strSQLConnectionString)
connTemp.Open()
connInsertSQL.Open()
Dim intReturn As Integer
Dim I As Integer
Dim strSQL As String = ""
Dim strSQLInsert As String = ""
Dim cmdInsertSQL As SqlClient.SqlCommand
For Each row As DataRow In table.Rows
    strSQL = "SELECT COUNT(*) AS NoOfRecords FROM MetDB WHERE ColumnA = @ColumnA AND " _
            & "ColumnB = @ColumnB AND ColumnC = @ColumnC AND MetNo = @MetNo"
    Dim cmdTemp As New SqlClient.SqlCommand(strSql, connTemp)
    With cmdTemp.Parameters
        .AddWithValue("@ColumnA", row("ColumnA"))
        .AddWithValue("@ColumnB", row("ColumnB"))
        .AddWithValue("@ColumnC", row("ColumnC"))
        .AddWithValue("@MetNo", lblMetNo.Text)
    End With
    intReturn = Convert.ToInt16(cmdTemp.ExecuteScalar)
    If (intReturn = 0) Then
        strSQLInsert = "INSERT INTO dbo.MetDB " _
                & "(ColumnA, ColumnB, ColumnC, ColumnD, ColumnE, ColumnF, ColumnG, ColumnH, ColumnI, ColumnJ, ColumnK, ColumnL, ColumnM, ColumnN, ColumnO, " _
                & "ColumnP, ColumnQ, ColumnR, ColumnS, ColumnT, ColumnU, ColumnV, ColumnW, MetNo) VALUES (@ColumnA, @ColumnB, @ColumnC, @ColumnD, " _
                & "@ColumnE, @ColumnF, @ColumnG, @ColumnH, @ColumnI, @ColumnJ, @ColumnK, @ColumnL, @ColumnM, @ColumnN, @ColumnO, @ColumnP, @ColumnQ, " _
                & "@ColumnR, @ColumnS, @ColumnT, @ColumnU, @ColumnV,  @ColumnW, @MetNo)"
        cmdInsertSQL = New SqlClient.SqlCommand(strSQLInsert, connInsertSQL)
        With cmdInsertSQL.Parameters
            cmdInsertSQL.Parameters.Add("@ColumnA", SqlDbType.Int, 4, "ColumnA")
            cmdInsertSQL.Parameters.Add("@ColumnB", SqlDbType.DateTime, 10, "ColumnB")
            cmdInsertSQL.Parameters.Add("@ColumnC", SqlDbType.Time, 8, "ColumnC")
            cmdInsertSQL.Parameters.Add("@ColumnD", SqlDbType.VarChar, 50, "ColumnD")
            cmdInsertSQL.Parameters.Add("@ColumnE", SqlDbType.VarChar, 50, "ColumnE")
            cmdInsertSQL.Parameters.Add("@ColumnF", SqlDbType.Decimal, 28, "ColumnF")
            cmdInsertSQL.Parameters("@ColumnF").Precision = 28
            cmdInsertSQL.Parameters("@ColumnF").Scale = 10
            cmdInsertSQL.Parameters.Add("@ColumnG", SqlDbType.VarChar, 50, "ColumnG")
            cmdInsertSQL.Parameters.Add("@ColumnH", SqlDbType.VarChar, 50, "ColumnH")
            cmdInsertSQL.Parameters.Add("@ColumnI", SqlDbType.Decimal, 28, "ColumnI")
            cmdInsertSQL.Parameters("@ColumnI").Precision = 28
            cmdInsertSQL.Parameters("@ColumnI").Scale = 10
            cmdInsertSQL.Parameters.Add("@ColumnJ", SqlDbType.VarChar, 50, "ColumnJ")
            cmdInsertSQL.Parameters.Add("@ColumnK", SqlDbType.Decimal, 28, "ColumnK")
            cmdInsertSQL.Parameters("@ColumnK").Precision = 28
            cmdInsertSQL.Parameters("@ColumnK").Scale = 10
            cmdInsertSQL.Parameters.Add("@ColumnL", SqlDbType.VarChar, 50, "ColumnL")
            cmdInsertSQL.Parameters.Add("@ColumnM", SqlDbType.Int, 10, "ColumnM")
            cmdInsertSQL.Parameters.Add("@ColumnN", SqlDbType.VarChar, 50, "ColumnN")
            cmdInsertSQL.Parameters.Add("@ColumnO", SqlDbType.Int, 4, "ColumnO")
            cmdInsertSQL.Parameters.Add("@ColumnP", SqlDbType.VarChar, 50, "ColumnP")
            cmdInsertSQL.Parameters.Add("@ColumnQ", SqlDbType.Int, 4, "ColumnQ")
            cmdInsertSQL.Parameters.Add("@ColumnR", SqlDbType.VarChar, 50, "ColumnR")
            cmdInsertSQL.Parameters.Add("@ColumnS", SqlDbType.Int, 4, "ColumnS")
            cmdInsertSQL.Parameters.Add("@ColumnT", SqlDbType.VarChar, 50, "ColumnT")
            cmdInsertSQL.Parameters.Add("@ColumnU", SqlDbType.Int, 4, "ColumnU")
            cmdInsertSQL.Parameters.Add("@ColumnV", SqlDbType.VarChar, 50, "ColumnV")
            cmdInsertSQL.Parameters.Add("@ColumnW", SqlDbType.Int, 4, "ColumnW")
            cmdInsertSQL.Parameters.Add("@MetNo", SqlDbType.VarChar, 6, "MetNo")
        End With
        cmdInsertSQL.ExecuteNonQuery()
    Else
        MsgBox("Record Exists", MessageBoxIcon.Error, "Error")
    End If
Next

结束子

【问题讨论】:

  • 我使用的代码与从stackoverflow.com/questions/31497825/… 获得的代码相同,它本身就可以正常工作。包括错误行。
  • 在您提到的问题中,您使用的是SqlDataAdapter 并使用DataTable 调用adapter.Update(table),因此在这种情况下,4 参数Parameters.Add 调用是有意义的,但是您这里没有这样做 - 你打电话给cmdInsertSQL.ExecuteNonQuery(),这是完全不同的。
  • 请注意,您可以使用多个字段在表中创建唯一键(又名主键),这可能会使事情变得更简单。除非服务器在您的本地网络之外,否则我不会同时使用参数化命令,只需使用动态 SQL 来构建 INSERT 语句。 IMO 对 SQL 注入的恐惧被夸大了。

标签: sql-server vb.net csv


【解决方案1】:

您没有说代码在哪里引发错误,但您如何为cmdInsertSQL 添加参数对我来说似乎不正确。您正在使用Parameters.Add 的4 参数重载,其中第4 个参数是sourceColumn,我认为(我自己从未使用过!)用于从DataTable 更新。

所以,我相信您当前的代码正在添加参数,但未指定值,因此出现错误。相反,您应该从row 中的匹配列中设置值:

cmdInsertSQL.Parameters.Add("@ColumnA", SqlDbType.Int, 4).Value = row("ColumnA")

【讨论】:

  • 使用不同的参数名称(@ColumnA->@ColA@ColumnB->@ColB@ColumnC->@ColC@MetNo->@MNo)在首先,SQL:strSQL = "SELECT COUNT(*) AS NoOfRecords FROM MetDB WHERE ColumnA = @ColumnA AND " _ & "ColumnB = @ColumnB AND ColumnC = @ColumnC AND MetNo = @MetNo"可以解决歧义,不是吗?
  • @Jigar 我不完全确定你在问什么,但我认为参数名称不相关 - 它们不会在命令之间发生冲突。我认为问题在于strSQLInsert SQL,以及您如何指定参数。你有没有按照我的建议尝试改变它,有什么不同吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 2014-05-07
  • 2017-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多