How can i resolve ExecucuteNonQuery throwing exception Incorrect syntex near '?' - vb.net

Dim StrSql = "update student set id=?"
Updated (StrSql,15)
Public Function Updated (ByVal strSql As String, ByVal ParamArray Parameters As String ())
For Each x In Parameters
cmd.Parameters.AddWithValue("?",x)
Next
cmd.ExecuteNonQuery()
End Function

You didn't leave us much to go on; as jmcilhinney points out, you need to add more detail to future questions. For example in this one you have code there that doesn't compile at all, doesnt mention the types of any variable, you don't give the name of the database...
...I'm fairly sure that "Incorrect syntax near" is a SQL Server thing, in which case you need to remember that it (re)uses named parameters, unlike e.g. Access which uses positional ones:
SQL Server:
strSql = "SELECT * FROM person WHERE firstname = #name OR lastname = #name"
...Parameters.AddWithValue("#name", "Lee")
Access:
strSql = "SELECT * FROM person WHERE firstname = ? OR lastname = ?"
...Parameters.AddWithValue("anythingdoesntmatterwillbeignored", "Lee")
...Parameters.AddWithValue("anythingdoesntmatterwillbeignoredalso", "Lee")
This does mean your function will need to get a bit more intelligent; perhaps pass a ParamArray of KeyValuePair(Of String, Object)
Or perhaps you should stop doing this way right now, and switch to using Dapper. Dapper takes your query, applies your parameters and returns you objects if you ask for them:
Using connection as New SqlConnection(...)
Dim p as List(Of Person) = Await connection.QueryAsync(Of Person)( _
"SELECT * FROM person WHERE name = #name", _
New With { .name = "John" } _
)
' use your list of Person objects
End Using
Yep, all that adding parameters BS, and executing the reader, and converting the results to a Person.. Dapper does it all. Nonquery are done like connection.ExecuteAsync("UPDATE person SET name=#n, age=#a WHERE id=#id", New With{ .n="john", .a=27, .id=123 })
http://dapper-tutorial.net

Please turn on Option Strict. This is a 2 part process. First for the current project - In Solution Explorer double click My Project. Choose Compile on the left. In the Option Strict drop-down select ON. Second for future projects - Go to the Tools Menu -> Options -> Projects and Solutions -> VB Defaults. In the Option Strict drop-down select ON. This will save you from bugs at runtime.
Updated(StrSql, 15)
Your Updated Function calls for a String array. 15 is not a string array.
Functions need a datatype for the return.
cmd.Parameters.AddWithValue("?", X)
cmd is not declared.
You can't possible get the error you mention with the above code. It will not even compile, let alone run and produce an error.
It is not very helpful to write a Function that is trying to be generic but is actually very limited.
Let us start with your Update statement.
Dim StrSql = "update student set id=?"
The statement you provided will update every id in the student table to 15. Is that what you intended to do? ID fields are rarely changed. They are meant to uniquely identify a record. Often, they are auto-number fields. An Update command would use an ID field to identify which record to update.
Don't use .AddWithValue. See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
Since you didn't tell us what database you are using I guessed it was Access because of the question mark. If it is another database change the connection, command and dbType types.
Using...End Using block ensures you connection and command are closed and disposed even if there is an error.
Private ConStr As String = "Your Connection String"
Public Function Updated(StudentNickname As String, StudentID As Integer) As Integer
Dim RetVal As Integer
Using cn As New OleDbConnection(ConStr),
cmd As New OleDbCommand("Update student set NickName = #NickName Where StudentID = #ID", cn)
cmd.Parameters.Add("#NickName", OleDbType.VarChar, 100).Value = StudentNickname
cmd.Parameters.Add("#ID", OleDbType.Integer).Value = StudentID
cn.Open()
RetVal = cmd.ExecuteNonQuery
End Using
Return RetVal
End Function
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim RowsUpdated = Updated("Jim", 15)
Dim message As String
If RowsUpdated = 1 Then
message = "Success"
Else
message = "Failure"
End If
MessageBox.Show(message)
End Sub
This code keeps your database code separated from user interface code.

Related

VB & Access: no value given for one or more required parameters when inserting data

Hello so I have a problem with my simple program that I'm practicing. I'm trying to insert data from vb input box to MS Access database, there are 5 columns in employeeInfo table but the other one is AutoNumber so I didn't include it in the code. The employeeDB has only 3 columns ID, username, pword but I didn't include ID since it's AutoNumber. When I hit the button to add data it will throw an error No value given for one or more required parameters # database_reader = cmd_personal.ExecuteReader even if I did input all the input box that has connection to the database.
Private Sub signUp_btn_Click(sender As Object, e As EventArgs) Handles signUp_btn.Click
Dim usernameInput As String = inputBoxUsername.Text
Dim inputPword As String = inputBoxPword.Text
Dim input_FirstName As String = FirstName_Box.Text
Dim input_MidName As String = MidName_Box.Text
Dim input_LastName As String = LastName_Box.Text
Dim input_ContactNum As String = ContactNumber_Box.Text
dbConnection.Open()
Dim str_personal As String
Dim str_acctInfo As String
str_personal = "INSERT INTO employeeInfo([FirstName], [MiddleName], [LastName], [PhoneNumber]) Values (?, ?, ?, ?)"
str_acctInfo = "INSERT INTO employeeDB([username], [password]) Values (?, ?)"
Dim cmd_personal As OleDbCommand = New OleDbCommand(str_personal, dbConnection)
Dim cmd_acctInfo As OleDbCommand = New OleDbCommand(str_acctInfo, dbConnection)
database_reader = cmd_personal.ExecuteReader
database_reader = cmd_acctInfo.ExecuteReader
database_reader.Read()
' Check If Input box has values
If usernameInput = "" Then
MessageBox.Show("Please Insert Username.")
inputBoxUsername.Clear()
ElseIf inputPword = "" Then
MessageBox.Show("Please Insert Password.")
ElseIf input_FirstName = "" Then
MessageBox.Show("Please insert First Name.")
ElseIf input_MidName = "" Then
MessageBox.Show("Please insert Middle Name.")
ElseIf input_LastName = "" Then
MessageBox.Show("Please insert Last Name.")
ElseIf input_ContactNum = "" Then
MessageBox.Show("Please insert Phone Number.")
End If
' Insert into employeeInfo DB
cmd_personal.Parameters.Add(New OleDbParameter("FirstName", CType(input_FirstName, String)))
cmd_personal.Parameters.Add(New OleDbParameter("MiddleName", CType(input_MidName, String)))
cmd_personal.Parameters.Add(New OleDbParameter("LastName", CType(input_LastName, String)))
cmd_personal.Parameters.Add(New OleDbParameter("PhoneNumber", CType(input_ContactNum, String)))
' Insert into employeeDB acct DB
cmd_acctInfo.Parameters.Add(New OleDbParameter("username", CType(usernameInput, String)))
cmd_acctInfo.Parameters.Add(New OleDbParameter("password", CType(inputPword, String)))
MessageBox.Show("Success! User has been created.")
dbConnection.Close()
I don't need advance solution just a simple one. Thanks!
(I already connect it to the Access Database I just didn't include the code at this post.)
If your SQL contains N ?, then you cannot call cmd_personal.ExecuteReader before you call cmd_personal.Parameters.Add N times to create the parameters (and give them a value)
If your intention is to call the command repeatedly, you can adopt a pattern of:
create command with ? placeholders
add parameters without values, or with representative dummy values if you're using "AddWithValue"/its equivalent (using the paramname,paramvalue constructor, as your code does, is equivalent to calling AddWithValue)
start a loop
set values
execute command
In this case it looks like your code is merely in the wrong order
Ok a few things. There is really no use to write a bunch of separate statements to test if a text box has a value. Like FoxPro, Access, dabase, or just about any system?
They have the ability to "validate" each text box.
So, move that code out. For each control that you want say as required?
So for say FirstName_Box?
Then in the events of the property sheet, use this event:
So, we double click in that Validating event, and we can write this:
Private Sub FirstName_Box_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles FirstName_Box.Validating
If FirstName_Box.Text = "" Then
MsgBox("First name is required")
e.Cancel = True
End If
End Sub
So, now if I click any button on the form, the text box will validate, and also pop up a nice message.
So, now we can dump, and assume our button code will not run until each control and its validation event is ok. It not only saves some code, but what happens if we have 2 or 4 buttons on the form, and now we going to write code to check all those text boxes each time? (nope!!!).
Ok, so now we can assume in our code that any required text box has a value. And if not, then the button click for any button code will not run for us - nice and simple, but more important nice and CLEAN. Since I can now know where to look for any code for a SINGLE control that has some criteria for input.
It also means that you have less code to work with, and deal with at one point in time.
This is much like the answer to this question:
How do you eat a elephant?
Answer: One bite at a time!!!
Ok, now that we have that all fixed up, we can clean up our code to insert.
I actually in a lot of cases suggest using a Datatable, since then we don't have to mess with parameters, but MORE important, it gives us the ability to EASY check if the information or "user" in this case already exists. I mean, you don't want to add the same user two times? Right?
So, now we can clean this up and ALSO check for if the user already exists.
Say somthing like this (warning: air code).
Using conn As New OleDbConnection(My.Settings.AccessDB)
conn.Open()
Dim strSQL As String =
"SELECT * FROM employeeDB WHERE UserName = #User"
Using cmdSQL As New OleDbCommand(strSQL, conn)
Dim da As New OleDbDataAdapter(cmdSQL)
Dim daU As New OleDbCommandBuilder(da)
cmdSQL.Parameters.Add("#User", OleDbType.VarWChar).Value = inputBoxUserName.Text
Dim rstAcctInfo As New DataTable
rstAcctInfo.Load(cmdSQL.ExecuteReader)
If rstAcctInfo.Rows.Count > 0 Then
MsgBox("This user already exists")
return ' bail out and exit
End If
' if we get here, user does not exist, so add this user
Dim OneRow As DataRow = rstAcctInfo.NewRow
OneRow("username") = inputBoxUsername.Text
OneRow("password") = inputBoxPword.Text
rstAcctInfo.Rows.Add(OneRow)
da.Update(rstAcctInfo) ' add this new user
' now add the data to personal
cmdSQL.Parameters.Clear()
cmdSQL.CommandText =
"INSERT INTO employeeInfo([FirstName], [MiddleName], [LastName], [PhoneNumber]) Values " &
"(#FN, #MN,#LN , #Phone)"
With cmdSQL.Parameters
.Add("#FN", OleDbType.VarWChar).Value = FirstName_Box.Text
.Add("#MN", OleDbType.VarWChar).Value = MidName_Box.Text
.Add("#LN", OleDbType.VarWChar).Value = LastName_Box.Text
.Add("#Phone", OleDbType.VarWChar).Value = ContactNumber_Box.Text
End With
cmdSQL.ExecuteNonQuery()
End Using
End Using

"Procedure or function expects parameter which was not supplied"

I've been trying to figure out this bug for a while now, some help would be appreciated. Thanks.
Here is my error message:
Procedure or function 'getAvailableSMSNumbers' expects parameter '#Election_ID', which was not supplied.
Here is my sql code:
CREATE PROCEDURE {databaseOwner}{objectQualifier}getAvailableSMSNumbers
#Election_ID nvarchar(20)
AS
SELECT *
FROM {databaseOwner}{objectQualifier}icc_sms_phones
LEFT JOIN {databaseOwner}{objectQualifier}icc_sms_elections ON sms_elections_sms_number = phones_number
WHERE sms_elections_sms_number IS NULL
OR sms_elections_id = #Election_ID
GO
Function:
Public Overrides Function getAvailableSMSNumbers(eventid As String) As IDataReader
Dim dtable As New DataTable
Using sqlconn As New SqlConnection(Me.ConnectionString)
Using sqlcomm As New SqlCommand
Using sqlda As New SqlDataAdapter
sqlcomm.Connection = sqlconn
sqlcomm.CommandType = CommandType.StoredProcedure sqlcomm.CommandText=GetFullyQualifiedName("getAvailableSMSNumbers")
sqlcomm.Parameters.AddWithValue("#Election_ID", eventid)
sqlda.SelectCommand = sqlcomm
sqlconn.Open()
sqlda.Fill(dtable)
sqlconn.Close()
Return dtable.CreateDataReader
End Using
End Using
End Using
End Function
Where the function is used:
Public Function getAvailableSMSNumbers(eventid As String) As List(Of phoneModel)
Dim numbers As New List(Of phoneModel)
Dim number As phoneModel
numbers = CBO.FillCollection(Of phoneModel)(dal.getAvailableSMSNumbers(eventid))
For Each number In numbers 'dal.getAvailableSMSNumbers(eventid).Rows
number = New phoneModel
With number
.val = ("PHONES_NUMBER").ToString
.text = String.Format("{0:# (###) ###-####}", Long.Parse(.val))
End With
numbers.Add(number)
Next
Return numbers
End Function
If you need anymore information, let me know, and I will add it.
This typically occurs if the object supplied as the value of your SQL parameter is NULL, but the stored procedure does not allow null values (which yours does not). You can set a conditional breakpoint on this line sqlcomm.Parameters.AddWithValue("#Election_ID", eventid) to make sure the eventid parameter is not null.
It might also be a good idea to use defensive coding, and in your getAvailableSMSNumbers function, check to make sure eventid is not null, and if it is, throw an exception or provide some type of feedback for the user.
As an option you can try to re-compile your stored procedure to allow NULL parameter :
CREATE PROCEDURE {databaseOwner}{objectQualifier}getAvailableSMSNumbers
#Election_ID nvarchar(20) = NULL
AS
That means that the default value of your Parameter will be null in case there is no value on input. This solution will be nice in case you want to return empty datatable without error. In any other case you have to debug your VB code and understand where the issue starts.
Think about how you are calling you procedure. When you call you need to supply the value of the procedure: For example,
Call get_particular_girl_from_girlsTable("Jane")
where get_particular_girl_from_girlsTable is the procedure and "Jane" is value for parameter GirlName.
Did you verify if
cmd.CommandType = CommandType.**StoredProcedure**
By default, the value is Text, expecting a SELECT, INSERT or other command text.

Database Lookup From ComboBox selection

I have a question about database values and how to determine the id of a value that has been changed by the user at some point.
As it is currently set up there is a combobox that is populated from a dataset, and subsequent text boxes whose text should be determined by the value chosen from that combobox.
So let's say for example you select 'Company A' from the combobox, I would like all the corresponding information from that company's row in the dataset to fill the textboxes (Name = Company A, Address = 123 ABC St., etc.,)
I am able to populate the combobox just fine. It is only however when I change the index of the combobox that this specific error occurs:
An unhandled exception of type 'System.Data.OleDb.OleDbException'
occurred in System.Data.dll
Additional information: Data type mismatch in criteria expression.
Here is the corresponding code:
Imports System.Data.OleDb
Public Class CustomerContact
Dim cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|datadirectory|\CentralDatabase.accdb;")
Dim da As New OleDbDataAdapter()
Dim dt As New DataTable()
Private Sub CustomerContact_Load(sender As Object, e As EventArgs) Handles MyBase.Load
cn.Open()
da.SelectCommand = New OleDbCommand("select * from Customers", cn)
da.Fill(dt)
Dim r As DataRow
For Each r In dt.Rows
cboVendorName.Items.Add(r("Name").ToString)
cboVendorName.ValueMember = "ID"
Next
cn.Close()
End Sub
Private Sub cboVendorName_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboVendorName.SelectedIndexChanged
cn.Open()
da.SelectCommand = New OleDbCommand("select * from Customers WHERE id='" & cboVendorName.SelectedValue & "'", cn)
da.Fill(dt)
Dim r As DataRow
For Each r In dt.Rows
txtNewName.Text = "Name"
txtAddress.Text = "Address"
Next
cn.Close()
End Sub
The error is caught at Line 24 of this code, at the second da.Fill(dt) . Now obviously from the exception I know that I am sending in a wrong datatype into the OleDbCommand, unfortunately I am a novice when it comes to SQL commands such as this. Also please keep in mind that I can't even test the second For loop, the one that is supposed to fill the Customer information into textboxes (for convenience I only copied the first two textboxes, of which there are nine in total). I am think I could use an If statement to determine if the row has been read, and from there populate the textboxes, but I will jump that hurdle when I can reach it.
Any guidance or suggestions would be much appreciated. Again I am a novice at managing a database and the code in question pertains to the project my current internship is having me write for them.
Since you already have all the data from that table in a DataTable, you dont need to run a query at all. Setup in form load (if you must):
' form level object:
Private ignore As Boolean
Private dtCust As New DataTable
...
Dim SQL As String = "SELECT Id, Name, Address, City FROM Customer"
Using dbcon = GetACEConnection()
Using cmd As New OleDbCommand(SQL, dbcon)
dbcon.Open()
dtCust.Load(cmd.ExecuteReader)
End Using
End Using
' pk required for Rows.Find
ignore = True
dtCust.PrimaryKey = New DataColumn() {dtCust.Columns(0)}
cboCust.DataSource = dtCust
cboCust.DisplayMember = "Name"
cboCust.ValueMember = "Id"
ignore = False
The ignore flag will allow you to ignore the first change that fires as a result of the DataSource being set. This will fire before the Display and Value members are set.
Preliminary issues/changes:
Connections are meant to be created, used and disposed of. This is slightly less true of Access, but still a good practice. Rather than connection strings everywhere, the GetACEConnection method creates them for me. The code is in this answer.
In the interest of economy, rather than a DataAdapter just to fill the table, I used a reader
The Using statements create and dispose of the Command object as well. Generally, if an object has a Dispose method, put it in a Using block.
I spelled out the columns for the SQL. If you don't need all the columns, dont ask for them all. Specifying them also allows me to control the order (display order in a DGV, reference columns by index - dr(1) = ... - among other things).
The important thing is that rather than adding items to the cbo, I used that DataTable as the DataSource for the combo. ValueMember doesn't do anything without a DataSource - which is the core problem you had. There was no DataSource, so SelectedValue was always Nothing in the event.
Then in SelectedValueChanged event:
Private Sub cboCust_SelectedValueChanged(sender As Object,
e As EventArgs) Handles cboCust.SelectedValueChanged
' ignore changes during form load:
If ignore Then Exit Sub
Dim custId = Convert.ToInt32(cboCust.SelectedValue)
Dim dr = dtCust.Rows.Find(custId)
Console.WriteLine(dr("Id"))
Console.WriteLine(dr("Name"))
Console.WriteLine(dr("Address"))
End Sub
Using the selected value, I find the related row in the DataTable. Find returns that DataRow (or Nothing) so I can access all the other information. Result:
4
Gautier
sdfsdfsdf
Another alternative would be:
Dim rows = dtCust.Select(String.Format("Id={0}", custId))
This would return an array of DataRow matching the criteria. The String.Format is useful when the target column is text. This method would not require the PK definition above:
Dim rows = dtCust.Select(String.Format("Name='{0}'", searchText))
For more information see:
Using Statement
Connection Pooling
GetConnection() method aka GetACEConnection

Is it possible to change the default decimal separator in float.ToString()?

I need to send data in string format to mysql. By default vb.net interprets 0.5 as 0,5 which MySql won't accept. I know I could write floatval.tostring.replace(",", ".") to make it fit but I was wondering if it was possible to make it more comfortable so that an implicit conversion from float to string would produce a dot instead of a comma?
EDIT: per request, current code
Public Sub InsertInto(Values As IEnumerable(Of String))
Dim ValStr As String = ""
For Each V In Values
ValStr &= "'" & V & "',"
Next
Dim Command = New MySqlCommand("INSERT INTO " & Table & " VALUES (" & ValStr.Substring(0, ValStr.Length - 1) & ");", Connection)
Command.ExecuteNonQuery()
End Sub
this method is a part of a mysql connection wrapper and the properties "Connection" and "Table" are preassigned.
My test code calls the function as follows:
dimdum.InsertInto({"DEFAULT", (0.5).ToString.Replace(",", "."), "here is text"})
the test table columns are auto iterating int as primary key, a float and a varchar
As I have saind in my comment above, I am afraid that you need to revise a lot of your code. As is you have a lot of problems, the worst is the Sql Injection that sooner or later you have to fix, but your try to convert everything in a string has also the drawback that the conversion of decimals, dates and other floating points values give more immediate troubles than the Sql Injection one.
There is only one way to get out and it is the use of parameterized queries. More code to write but after a while it is very straightforward.
So for example you should rewrite your code to something like this
Public Sub InsertInto(sqlText As String, Values As List(Of MySqlParameter))
Using Connection = New MySqlConnection(... connectionstring here (or a global variable ....)
Using Command = New MySqlCommand(sqlText, Connection)
Connection.Open()
If Values IsNot Nothing Then
Command.Parameters.AddRange(values.ToArray)
End If
Command.ExecuteNonQuery()
End Using
End Using
End Sub
and call it with this
Dim decValue As Decimal = 0.5
Dim strValue As String = "Test"
Dim dateValue As DateTime = DateTime.Today
Dim parameters = New List(Of MySqlParameter)()
parameters.Add(New MySqlParameter() With { .ParameterName = "#p1",
.DbType = MySqlDbType.Decimal,
.Value = decValue})
parameters.Add(New MySqlParameter() With {.ParameterName = "#p2",
.DbType = MySqlDbType.String,
.Value = strValue})
parameters.Add(New MySqlParameter() With {.ParameterName = "#p3",
.DbType = MySqlDbType.Date,
.Value = dateValue})
InsertInto("INSERT INTO youTable VALUES(#p1, #p2, #p3)", parameters)
Note that now InserInto is just a simple routine that receives the command text and the parameters expected by the text, add them to the command, opens the connection, executes everything and exits closing the connection.
Note also that, with a parameterized queries, your sql command is totally void of the mess caused by single quotes for strings, formatting rules for dates and the handling of the decimal point is nowhere in sight
(A side note. This INSERT INTO text suppose that your table has exactly three fields and you supply the values for all of them, if you want to insert only a subset of fields then you need to pass them to the method as a third parameter )
Specify CultureInfo:
Dim n As Single
Dim s As String
n = Math.PI
s = n.ToString("F2", New System.Globalization.CultureInfo("en-US"))
s will be "3.14", even if your computer is set for a different format.

Auto update access tables Cells with random numbers from vb.net

I searched many forums but didn't find any solution. I want to update access table cells from Vb.net. My table has fields:
[PanelNumber],[Date], [PVValue]
In Panel number field, there is some text like "Panel 1", "Panel 2" etc..
from vb, i will select that "Panel 1" after clicking a button, i need to fill that "PVValue" field with random numbers in given range, plz check my code below, when i try with this code, i am always getting same number in all rows
but need separate number (may be repeated in some rows)
LogTable2 is my table name
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=LoggedData.accdb;Jet OLEDB:Database Password=GodavarthiSuresh;"
myNewConnection.ConnectionString = connString
myNewConnection.Open()
Dim UpdateString As String = "update LogTable2 set [pvvalue]= #rndVal1 where panelnumber='" & panelnametxt.Text & "'"
Dim UpdateCmd As New OleDb.OleDbCommand(UpdateString, myNewConnection)
UpdateCmd.Parameters.Clear()
Randomize()
UpdateCmd.Parameters.AddWithValue("#rndVal1", GetRandom())
Try
UpdateCmd.ExecuteNonQuery()
UpdateCmd.Dispose()
myNewConnection.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
' this is the function to get random number in given range
Public Function GetRandom() As Integer
Static Generator As System.Random = New System.Random()
Return Generator.Next(825, 850)
End Function
If you have multiple rows for each panel and you want them to have different values, you need to update them individually. Its is not true that update command will be "called" 5 times if there are five rows associated. It will be executed once per click event.
To do what it sounds like you want, you need a unique identifier for each such as an AutoIncrement ID column.
Private RNG As New Random()
Private Sub btnUpdate_Click(etc...
Dim sql = "SELECT ID FROM LogTable2 WHERE panelnumber = #pnl"
Dim pnlList As New List(Of Int32)
Using con As OleDbConnection = GetACEConnection()
Using cmd As New OleDbCommand(sql, con)
con.Open()
cmd.Parameters.AddWithValue("#pnl", panelnametxt.Text)
' get affected row IDs into a list;
Using rdr As OleDbDataReader = cmd.ExecuteReader
While rdr.Read
pnlList.Add(Convert.ToInt32(rdr.Item("ID")))
End While
End Using ' close, dispose of reader
End Using ' dispose of cmd
' not sure you need a new command object
sql = "UPDATE LogTable2 SET pvvalue = #rVal WHERE ID = #id"
Using pcmd As New OleDbCommand(sql, con)
' loop thru ID list and update each row with
' new random value 825-849 inclusive
For n As Int32 = 0 To pnlList.Count - 1
pcmd.Parameters.AddWithValue("#rVal", RNG.Next(825, 850))
pcmd.Parameters.AddWithValue("#id", pnlList(n))
pcmd.ExecuteNonQuery()
' clear for next iteration
pcmd.Parameters.Clear()
Next
End Using ' close and dispose of pcmd
End Using ' close and dispose of connection
End Sub
I dont like scattering the connection string in every method which opens a connection, so a method for that is nice to have.
Notes:
This depends on a unique ID column which is AutoIncrement (PK). If you have some other unique identifier, use it but you have to have some way to identify rows individually.
Rather than a method to create a random value, since it is just one line, it might be easier to just use your RNG directly as shown.
I cant test the code, but it should be close.
Use Using blocks to close and dispose of DBObjects like connections, command and reader otherwise you can run out of resources.
You can also initialize Command objects with the SQL and COnnection when you declare it rather than setting them as properties. It makes the code a little more compact and less likely that you forget them.
Randomize does nothing - it is meant to be used with the old VB6 Rnd(). You only need to [Escape] keywords in SQL, not every column name and pvvalue is not a keyword.
A DataTable instead of a Reader could be used to get the rows but I am not sure it is any simpler.
Finally, elements of a SQL WHERE clause can also be parameterized; there is no need to concat them just because it is a where rather than a column value.
you can do this in database level,add auto increment value to database field