Question

I am quite new to VB.NET programming so forgive my ignorance. I am trying to update data from an excel spreadsheet to a SQL database by using OLEDB to get the excel information and then passing the OLEDB info to parameters for a SQLCommand update. The For statement area seems to be the problem as I keep getting the error below. I added some messageboxes to see if I was getting data in paraArray(i) and excelArray(i) and it worked and looped perfectly. Just do not know why it is saying I have not declared the variable when I execute the sqlCmd.ExecuteScalar

ERROR: "An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll. Additional information: Must declare the scalar variable "@INGREDIENTS".

If you need clarification I will provide. This is my first post on stackoverflow. I am excited to hear the experts.

sqlUpdate = "UPDATE xxxxx.dbo.testtable SET INGREDIENTS= @INGREDIENTS, SERVINGSIZE= @SERVINGSIZE where SPC= @SPC"

Dim sqlCon As New SqlConnection("Server=Myserver;Database=MyDatabase;User Id=xx;Password=xxxxx")
            sqlCon.Open()

Dim excelCmd2 As New System.Data.OleDb.OleDbCommand("SELECT * FROM [" + sheetName + "]", con)
Dim sqlQuery As New System.Data.SqlClient.SqlCommand("SELECT * FROM xxxxx.dbo.testtable", sqlCon)

Using dataRead As System.Data.OleDb.OleDbDataReader = excelCmd2.ExecuteReader()
                    If dataRead.HasRows() Then
                        While dataRead.Read()

                            Dim sqlCmd As New SqlCommand
                            sqlCmd.Connection = sqlCon
                            sqlCmd.CommandType = CommandType.Text
                            sqlCmd.CommandText = sqlUpdate

                            Dim paraArray() As String = {"@SPC","@INGREDIENTS","@SERVINGSIZE"} 
                            Dim excelArray() As String = {"SPC", "INGREDIENTS", "SERVINGSIZE"}
                            Dim i As Integer = 0

                            For i = 0 To 2                                    
                                sqlCmd.Parameters.AddWithValue(paraArray(i), SqlDbType.Variant).Value = Convert.ToString(dataRead.Item(excelArray(i)))
                                sqlCmd.ExecuteScalar()
                            Next

                        End While        
                    End If
                End Using

New Code after the correct answer by Bjorn and detail explanation by Steve.

sqlUpdate = "UPDATE xxxxx.dbo.testtable SET INGREDIENTS= @INGREDIENTS, SERVINGSIZE= @SERVINGSIZE where SPC= @SPC"

    Dim sqlCon As New SqlConnection("Server=Myserver;Database=MyDatabase;User Id=xx;Password=xxxxx")
                sqlCon.Open()

    Dim excelCmd2 As New System.Data.OleDb.OleDbCommand("SELECT * FROM [" + sheetName + "]", con)
    Dim sqlQuery As New System.Data.SqlClient.SqlCommand("SELECT * FROM xxxxx.dbo.testtable", sqlCon)
Dim paraArray() As String = {"@SPC", "@INGREDIENTS", "@SERVINGSIZE", "@SERV_IN_GRAMS", "@SERV_PER_CON", "@CALORIES", "@CALORIES_FAT", "@TOTAL_FAT", "@SAT_FAT", "@TRANS_FAT", "@POLY_FAT", "@MONO_FAT", "@CHOLESTEROL", "@POTASSIUM", "@SODIUM", "@TOTAL_CARB", "@DIET_FIBER", "@SUGARS", "@SUGAR_ALC", "@PROTEIN", "@VIT_A", "@VIT_C", "@CAL", "@IRON", "@VIT_D", "@VIT_E", "@VIT_K", "@THIAMIN", "@ROBO", "@NIACIN", "@VIT_B12", "@BIOTIN", "@PANTO_ACID", "@PHOSPHORUS", "@IODINE", "@MAGNESIUM", "@ZINC", "@SELENIUM", "@COPPER", "@MANGANESE", "@CHROMIUM", "@MOLYBDENUM", "@FOLATE", "@VIT_B6", "@CHLORIDE", "@PH", "@WATER_CONTENT", "@MOISTURE", "@FAT_PERCENT", "@ASH", "@SULFUR_DIOXIDE", "@PEROXIDE", "@SORBIC_ACID", "@TOTAL_PLATE", "@YEAST_MOLD", "@ENTER_BACT", "@COLIFORM", "@ECOLI", "@SALMONELLA", "@STAPH_AUR", "@LISTEROA", "@KOSHER", "@HALAL", "@ORGANIC", "@ALL_NAT", "@VEGETAR", "@VEGAN", "@RAW", "@SPROUTED", "@GLUTEN", "@WHEAT", "@CASEIN", "@CORN", "@DAIRY", "@EGG", "@GMO", "@LACTOSE", "@PEANUT", "@TREE_NUT", "@SOY", "@YEAST", "@SHELL_FISH", "@FISH", "@RECYCLE", "@BEEF_GRADE", "@CHILD_NUT", "@MARINE_CERT"}
            Using dataRead As System.Data.OleDb.OleDbDataReader = excelCmd2.ExecuteReader()
                If dataRead.HasRows() Then

                    Dim sqlCmd As New SqlCommand
                    sqlCmd.Connection = sqlCon
                    sqlCmd.CommandType = CommandType.Text
                    sqlCmd.CommandText = sqlUpdate
                    For i = 0 To paraArray.Length - 1
                        sqlCmd.Parameters.AddWithValue(paraArray(i), String.Empty)
                    Next
                    Dim excelArray() As String = {"SPC", "INGREDIENTS", "SERVINGSIZE", "SERV_IN_GRAMS", "SERV_PER_CON", "CALORIES", "CALORIES_FAT", "TOTAL_FAT", "SAT_FAT", "TRANS_FAT", "POLY_FAT", "MONO_FAT", "CHOLESTEROL", "POTASSIUM", "SODIUM", "TOTAL_CARB", "DIET_FIBER", "SUGARS", "SUGAR_ALC", "PROTEIN", "VIT_A", "VIT_C", "CAL", "IRON", "VIT_D", "VIT_E", "VIT_K", "THIAMIN", "ROBO", "NIACIN", "VIT_B12", "BIOTIN", "PANTO_ACID", "PHOSPHORUS", "IODINE", "MAGNESIUM", "ZINC", "SELENIUM", "COPPER", "MANGANESE", "CHROMIUM", "MOLYBDENUM", "FOLATE", "VIT_B6", "CHLORIDE", "PH", "WATER_CONTENT", "MOISTURE", "FAT_PERCENT", "ASH", "SULFUR_DIOXIDE", "PEROXIDE", "SORBIC_ACID", "TOTAL_PLATE", "YEAST_MOLD", "ENTER_BACT", "COLIFORM", "ECOLI", "SALMONELLA", "STAPH_AUR", "LISTEROA", "KOSHER", "HALAL", "ORGANIC", "ALL_NAT", "VEGETAR", "VEGAN", "RAW", "SPROUTED", "GLUTEN", "WHEAT", "CASEIN", "CORN", "DAIRY", "EGG", "GMO", "LACTOSE", "PEANUT", "TREE_NUT", "SOY", "YEAST", "SHELL_FISH", "FISH", "RECYCLE", "BEEF_GRADE", "CHILD_NUT", "MARINE_CERT"}
                    While dataRead.Read()
                        For i = 0 To excelArray.Length - 1

                            sqlCmd.Parameters(i).Value = Convert.ToString(dataRead.Item(excelArray(i)))
                        Next
                        sqlCmd.ExecuteNonQuery()
                    End While

                End If
            End Using
Was it helpful?

Solution

Move the ExecuteScalar outside the loop

For i = 0 To 2                                    
    sqlCmd.Parameters.AddWithValue(paraArray(i), SqlDbType.Variant).Value = _
           Convert.ToString(dataRead.Item(excelArray(i)))
Next
sqlCmd.ExecuteNonQuery()

In your code the command is executed too early. You have added only the first parameter and so you get the error. (By the way, that is not the correct syntax for AddWithValue which requires the parameter name and, as second parameter, the value to be used)

Not related to you problem, but ExecuteScalar is used to retrieve a value (the first column of the first row) from an SELECT query. It works also for other kind of queries but the recommended method for INSERT/UPDATE/DELETE is ExecuteNonQuery that returns the number of rows involved by your command

I also suggest a small optimization to your code. Move the creation of the SqlCommand outside the loop on the DataReader and inside the loop update only the values without recreating the command and the parameter collection

 Dim paraArray() As String = {"@SPC","@INGREDIENTS","@SERVINGSIZE"} 
 Using dataRead As System.Data.OleDb.OleDbDataReader = excelCmd2.ExecuteReader()
    If dataRead.HasRows() Then
        Dim sqlCmd As New SqlCommand
        sqlCmd.Connection = sqlCon
        sqlCmd.CommandType = CommandType.Text
        sqlCmd.CommandText = sqlUpdate
        For i = 0 To paraArray.Length - 1                                    
            sqlCmd.Parameters-AddWithValue(paraArray(i), string.Empty)
        Next

        Dim excelArray() As String = {"SPC", "INGREDIENTS", "SERVINGSIZE"}
        While dataRead.Read()
            Dim i As Integer = 0
            For i = 0 To excelArray.Lenth - 1
                sqlCmd.Parameters(i).Value = Convert.ToString(dataRead.Item(excelArray(i)))
            Next
            sqlCmd.ExecuteNonQuery()
        End While        
    End If
End Using

OTHER TIPS

You're executing the command before all parameters are set:

For i = 0 To 2                                    
    sqlCmd.Parameters.AddWithValue(paraArray(i), SqlDbType.Variant).Value = Convert.ToString(dataRead.Item(excelArray(i)))
    'Executes in first cycle and fails:
    sqlCmd.ExecuteScalar()
Next

So just move the sqlCmd.ExecuteScalar() outside the loop:

For i = 0 To 2                                    
    sqlCmd.Parameters.AddWithValue(paraArray(i), SqlDbType.Variant).Value = Convert.ToString(dataRead.Item(excelArray(i)))
Next

sqlCmd.ExecuteScalar()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top