【发布时间】: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