How to use parameters "#" in an SQL command in VB - sql

I have this code to update my SQL database from data in a textbox, in VB. I need to use parameters in case the text contains a tic mark ,', or a quote ,", etc. Here is what I have:
dbConn = New SqlConnection("server=.\SQLEXPRESS;Integrated Security=SSPI; database=FATP")
dbConn.Open()
MyCommand = New SqlCommand("UPDATE SeansMessage SET Message = '" & TicBoxText.Text & _
"'WHERE Number = 1", dbConn)
MyDataReader = MyCommand.ExecuteReader()
MyDataReader.Close()
dbConn.Close()
And this is my lame attempt to set a parameter from what I have seen on the web, which I don't understand all that well.
dbConn = New SqlConnection("server=.\SQLEXPRESS;Integrated Security=SSPI; database=FATP")
dbConn.Open()
MyCommand = New SqlCommand("UPDATE SeansMessage SET Message = #'" & TicBoxText.Text & _
"'WHERE Number = 1", dbConn)
MyDataReader = MyCommand.ExecuteReader()
MyDataReader.Close()
dbConn.Close()
How do you do this? Cause if there is a ' mark in the textbox when I run the code, it crashes.

You are on the right path to avoiding Bobby Tables, but your understanding of # parameters is incomplete.
Named parameters behave like variables in a programming language: first, you use them in your SQL command, and then you supply their value in your VB.NET or C# program, like this:
MyCommand = New SqlCommand("UPDATE SeansMessage SET Message = #TicBoxText WHERE Number = 1", dbConn)
MyCommand.Parameters.AddWithValue("#TicBoxText", TicBoxText.Text)
Note how the text of your command became self-contained: it no longer depends on the value of the text from the text box, so the users cannot break your SQL by inserting their own command. #TicBoxText became a name of the variable that stands for the value in the text of the command; the call to AddWithValue supplies the value. After that, your ExecuteReader is ready to go.

There are a number of improvements in here:
Using dbConn As New SqlConnection("server=.\SQLEXPRESS;Integrated Security=SSPI; database=FATP"), _
MyCommand As SqlCommand("UPDATE SeansMessage SET Message = #Message WHERE Number = 1", dbConn)
'Make sure to use your exact DbType (ie: VarChar vs NVarChar) and size
MyCommand.Parameters.Add("#Message", SqlDbType.VarChar).Value = TicBoxText.Text
dbConn.Open()
MyCommand.ExecuteNonQuery() ' don't open a data reader: just use ExecuteNonQuery
End Using 'Using block will close the connection for you

Related

Why is SQL not picking up parameter

I'm executing the code below but i am getting an error message saying that one or more required parameters is not provided. The only parameter that I can see is the strMyDomain which is provided. I put the MessageBox statement in temporarily just to confirm that the variable is getting a value. I must not have coded the SQL correctly to pick the value up but I can't see the error.
Dim strMyDomain = Environment.UserDomainName
MessageBox.Show("User domain is: " & strMyDomain)
Dim tblArchTable As New DataTable
Using myConn As New OleDbConnection(strConnectionString)
Dim adpArchives As New OleDbDataAdapter("SELECT ArchID, ArchUserName, ArchUserDomain, ArchDate, ArchRoot, ArchStatus FROM Archives WHERE ArchUserDomain = strMyDomain;", myConn)
adpArchives.Fill(tblArchTable)
DataGV1.DataSource = tblArchTable
End Using
It should be like this :
Dim adpArchives As New OleDbDataAdapter("SELECT ArchID, ArchUserName, ArchUserDomain,
ArchDate, ArchRoot, ArchStatus FROM Archives WHERE ArchUserDomain = '" & strMyDomain & "'", myConn)
But it has sql injection risk, best practice is to use parameterized query like below :
Dim adpArchives As New OleDbDataAdapter("SELECT ArchID, ArchUserName, ArchUserDomain,
ArchDate, ArchRoot, ArchStatus FROM Archives WHERE ArchUserDomain = ?", myConn)
adpArchives.SelectCommand.Parameters.Add(New OleDbParameter("#strMyDomain", strMyDomain))
The OLE DB .NET Provider does not support named parameters for passing parameters to an SQL statement or a stored procedure called by an OleDbCommand when CommandType is set to Text. In this case, the question mark (?) placeholder must be used.
For more detail, please read this

Having trouble understanding the # parameter in a SQL command

Good morning,
I am having trouble understanding the # parameter in vb.net. if we take the example code for the msdn:
' Update the demographics for a store, which is stored
' in an xml column.
Dim commandText As String = _
"UPDATE Sales.Store SET Demographics = #demographics " _
& "WHERE CustomerID = #ID;"
Using connection As New SqlConnection(connectionString)
Dim command As New SqlCommand(commandText, connection)
' Add CustomerID parameter for WHERE clause.
command.Parameters.Add("#ID", SqlDbType.Int)
command.Parameters("#ID").Value = customerID
' Use AddWithValue to assign Demographics.
' SQL Server will implicitly convert strings into XML.
command.Parameters.AddWithValue("#demographics", demoXml)
There seem to be no problem at all, however when you try to add more parameters into the mix, it does not seems to work. What would be the correct syntax to add more than one parameter?
Here is my piece of code:
query &= "INSERT INTO "
query &= imageProcAlgo.GetSqlTable()
query &= " ( #dateTimeStampCol , #numberOfBlobsCol , #AvgLengthCol , #avgWidthCol ) "
query &= "Values (#dtsvalue, #nbOfBlobsValue, #avgLengthValue, #avgWidthValue)"
and here where I try to add values to those parameters:
Using conn As New SqlConnection(connectStr)
Using comm As New SqlCommand(query)
With comm
.Connection = conn
.CommandType = CommandType.Text
.Parameters.AddWithValue("#dateTimeStampCol", "DateTimeStamp")
.Parameters.AddWithValue("#numberOfBlobsCol", "NumberOfBlob")
.Parameters.AddWithValue("#AvgLengthCol", "AvgWidth")
.Parameters.AddWithValue("#avgWidthCol", "AvgLength")
.Parameters.AddWithValue("#dtsvalue", "CURRENT_TIMESTAMP")
.Parameters.AddWithValue("#nbOfBlobsValue", imageProcAlgo.GetnumberOfBlobs().ToString())
.Parameters.AddWithValue("#avgLengthValue", imageProcAlgo.GetAvgWidth())
.Parameters.AddWithValue("#avgWidthValue", imageProcAlgo.GetAvgLength())
End With
Try
conn.Open()
comm.ExecuteNonQuery()
conn.Close()
Catch ex As SqlException
MessageBox.Show(ex.Message.ToString(), "Error Message")
End Try
End Using
When I try to execute this piece of code, I get an error saying that #datetimestampcol and so on are not valid column names.
I don't seem to understand what is the difference between the MSDN anf my code but i feel pretty close.. Any pointers for me to understand a bit better? to figure out where I went wrong?
Thanks,

No value given for one or more required parameters error vb.net

no_hp = TextBox1.Text
alamat = TextBox2.Text
password = TextBox3.Text
cmd = New OleDbCommand("UPDATE [user] SET no_hp = '" & CInt(TextBox1.Text) & "',alamat = " & TextBox2.Text & ", pin ='" & CInt(TextBox3.Text) & "' WHERE id = " & id & "", conn)
cmd.Connection = conn
cmd.ExecuteReader()
i was trying to update my access database with the following error
i cant seem to see where i did wrong
i already changed the data type from the textbox to match with the data types used in the database
the no_hp and pin is integer so i converted it to Cint but it doesnt seem to work
i already tried to substitute it to a variable but still it didnt work
please tell me where i did wrong
Use Parameters to avoid SQL injection, a malious attack that can mean data loss. The parameter names in Access do not matter. It is the order that they are added which must match the order in the SQL statement that matters.
The Using...End Using statements ensure that you objects are closed and disposed even it there is an error. This is most important for connections.
You con't need to set the connection property of the command because you passed the connection in the constructor of the command.
ExcuteReader is for retrieving data. Use ExecuteNonQuery to update, insert of delete.
Private Sub UpdateUsers()
Using conn As New OleDbConnection("Your connection string")
Using cmd = New OleDbCommand("UPDATE [user] SET no_hp = ?,alamat = ?, pin =? WHERE id = ?", conn)
cmd.Parameters.Add("nohp", OleDbType.Integer).Value = CInt(TextBox1.Text)
cmd.Parameters.Add("alamat", OleDbType.VarChar).Value = TextBox2.Text
cmd.Parameters.Add("pword", OleDbType.Integer).Value = CInt(TextBox3.Text)
cmd.Parameters.Add("id", OleDbType.Integer).Value = id
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End Sub

Error: Variable Names must be unique within a query batch or stored procedure

I successfully retrieve all my data from my database but whenever i try it for a second time an error occured saying that the variable name #uid has already been declared..
these are my codes. I dispose my sqlcommandbuilder and close my datareader everytime i used it.. but still no luck in finding the error at my codes.. please help me.. and also whenever i save and update data on my database.. it always succeed on the first try.. but on the second try.. it gets the same error "Variable Names must be unique within a query batch or stored procedure".
Sub fillDataFields()
Dim arrImage As Byte()
con.Open()
comm.CommandText = "Select last_name + ', ' + first_name + ' ' + middle_name as name,course, section, address, " & _
"birthday, picture from Users where user_id like #uid"
comm.Connection = con
comm.Parameters.AddWithValue("#uid", "" & frmUsers.ListView1.SelectedItems(0).Text & "%")
dr = comm.ExecuteReader
While (dr.Read())
arrImage = dr.Item("picture")
Dim mstream As New System.IO.MemoryStream(arrImage)
txtCourse.Text = (dr("course"))
txtSection.Text = (dr("section"))
richtxtAddress.Text = (dr("address"))
txtBirthday.Text = (dr("birthday"))
txtName.Text = (dr("name"))
PictureBox1.Image = Image.FromStream(mstream)
End While
con.Close()
dr.Close()
comm.Dispose()
End Sub
Your command object still has the parameter attached to it, so you should make sure you create a new instance of your objects and properly dispose of them after you have finished:
con = New Connection("connection string here")
con.Open()
comm = New Command
comm.CommandText = "command text here"
Then after you have finished with it dispose of it:
comm.Dispose
con.Close
con.Dispose
Even better wrap it in a Using block as this ensures it is disposed of for you:
Using con As New Connection("your connection String Here"), comm as New Command
con.Open()
comm.CommandText = "command text here"
...
...
con.Close
End Using 'con and comm objects are disposed here
Side note: I would suggest renaming your Command object something like cmd so that it doesn't look so similar to the Connection object.

How do I assign the results of an SQL query to multiple variables in VB.NET?

This is my first attempt at writing a program that accesses a database from scratch, rather than simply modifying my company's existing programs. It's also my first time using VB.Net 2010, as our other programs are written in VB6 and VB.NET 2003. We're using SQL Server 2000 but should be upgrading to 2008 soon, if that's relevant.
I can successfully connect to the database and pull data via query and assign, for instance, the results to a combobox, such as here:
Private Sub PopulateCustomers()
Dim conn As New SqlConnection()
Dim SQLQuery As New SqlCommand
Dim daCustomers As New SqlDataAdapter
Dim dsCustomers As New DataSet
conn = GetConnect()
Try
SQLQuery = conn.CreateCommand
SQLQuery.CommandText = "SELECT Customer_Name, Customer_ID FROM Customer_Information ORDER BY Customer_Name"
daCustomers.SelectCommand = SQLQuery
daCustomers.Fill(dsCustomers, "Customer_Information")
With cboCustomer
.DataSource = dsCustomers.Tables("Customer_Information")
.DisplayMember = "Customer_Name"
.ValueMember = "Customer_ID"
.SelectedIndex = -1
End With
Catch ex As Exception
MsgBox("Error: " & ex.Source & ": " & ex.Message, MsgBoxStyle.OkOnly, "Connection Error !!")
End Try
conn.Close()
End Sub
I also have no problem executing a query that pulls a single field and assigns it to a variable using ExecuteScalar. What I haven't managed to figure out how to do (and can't seem to hit upon the right combination of search terms to find it elsewhere) is how to execute a query that will return a single row and then set various fields within that row to individual variables.
In case it's relevant, here is the GetConnect function referenced in the above code:
Public Function GetConnect()
conn = New SqlConnection("Data Source=<SERVERNAME>;Initial Catalog=<DBNAME>;User Id=" & Username & ";Password=" & Password & ";")
Return conn
End Function
How do I execute a query so as to assign each field of the returned row to individual variables?
You probably want to take a look at the SqlDataReader:
Using con As SqlConnection = GetConnect()
con.Open()
Using cmd As New SqlCommand("Stored Procedure Name", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add("#param", SqlDbType.Int)
cmd.Parameters("#param").Value = id
' Use result to build up collection
Using dr As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection Or CommandBehavior.SingleResult Or CommandBehavior.SingleRow)
If (dr.Read()) Then
' dr then has indexed columns for each column returned for the row
End If
End Using
End Using
End Using
Like #Roland Shaw, I'd go down the datareader route but an other way.
would be to loop through
dsCustomers.Tables("Customer_Information").Rows
Don't forget to check to see if there are any rows in there.
Google VB.Net and DataRow for more info.