I am trying to export some data from a SQL Express table to Access using VB.net. The data is correctly displayed in SQL as, for example, temperature with the small degree object and the letters F or C for Farenhiet or Celsius. The character is of course represented by ° = "°" in html code, which is what appears in my access tables.
How can I get the insert statements to correctly pass this symbol? I have thousands of records and this applies to maybe a hundred or so in each of a few hundred DB's I am running this conversion on.
I read the data from a Gridview an .aspx .net web page and then use an insert query with an Access OLEDB connection.
SQLString1 = "INSERT INTO tblFornStrings (Str_ID, Code, Str_Name, Srt_Text, Lng_Text, Alt_Text) "
SQLString1 = SQLString1 & "VALUES ('" & StrngID & "', "
SQLString1 = SQLString1 & "'" & Code & "',"
SQLString1 = SQLString1 & "'" & Str_Name & "',"
SQLString1 = SQLString1 & "'" & newText1 & "',"
SQLString1 = SQLString1 & "'" & newText2 & "',"
SQLString1 = SQLString1 & "'" & newText3 & "')"
' SQLString1 = SQLString1 & "'" & tblSource & "')"
Dim dbCommand1 = New OleDbCommand(SQLString1, pConn)
pConn.Open()
dbCommand1.ExecuteNonQuery()
dbCommand1 = Nothing
These are the two fields that have the data, newText1 = Srt_Text, newText2 = Lng_Text
I have now tried to make this a parameterized query, having read that it would allow the string to be copied without an encoding issue. It did not work. Here is another version of the INSERT code using the parameters.
Dim SqlString As String = "INSERT INTO Strings (Str_ID, Code, Str_Name, Srt_Text, Lng_Text, Alt_Text) Values (?,?,?,?,?,?)"
Using cmd As New OleDbCommand(SqlString, pConn)
cmd.CommandType = CommandType.Text
cmd.Parameters.AddWithValue("Str_ID", StrngID)
cmd.Parameters.AddWithValue("Code", Code)
cmd.Parameters.AddWithValue("Str_Name", Str_Name)
cmd.Parameters.AddWithValue("Srt_Text", newText1)
cmd.Parameters.AddWithValue("Lng_Text", newText2)
cmd.Parameters.AddWithValue("Alt_Text", newText3)
pConn.Open()
cmd.ExecuteNonQuery()
pConn.Close()
End Using
The output is the same as is dispalyed in the graphic for the output of the first code block.
Thanks for any suggestions.
So you have some strings extracted from Gridview, and so far you were using those strings "as is" to build SQL statements (or to set parameter values for a parameterized database command). Now, what happens if, instead of using them "as is" you'd decode them first - e.g. by passing them to HttpUtility.HtmlDecode(...) method? (See this MSDN page for more details.)
Related
So here is the predefined SQL statement that is stored in the DAO file. The values are coming from a class. The picture value is an image converted to a byte(). This class is written in VB.net. I'm in a new job and in my previous i used angular and the entity framework so writing SQL statements is new to me. I'm trying to follow existing examples from co workers but they have never inserted images into the database before so i'm kinda on my own. Yes i know i could just store the files in the server and save the paths to them in the database but for whatever reason my network team wants it stored in the database as blobs. So, here is the SQL statement.
"INSERT INTO AuthAccessID" &
"(" &
"FName," &
"MName," &
"LName," &
"Suffix," &
"Address," &
"AddressExt," &
"City," &
"State," &
"Zip," &
"LawFirm," &
"Picture," &
"AddedDate," &
"AddedBy," &
")" &
"VALUES(" &
"" & ReplaceApostrophes(pp.FName) & ", " &
"'" & ReplaceApostrophes(pp.MName) & "', " &
"'" & ReplaceApostrophes(pp.LName) & "', " &
"'" & ReplaceApostrophes(pp.Suffix) & "', " &
"'" & ReplaceApostrophes(pp.Address) & "', " &
"'" & ReplaceApostrophes(pp.AddressExt) & "', " &
"'" & ReplaceApostrophes(pp.City) & "', " &
"'" & ReplaceApostrophes(pp.State) & "', " &
"'" & ReplaceApostrophes(pp.Zip) & "', " &
"'" & ReplaceApostrophes(pp.LawFirm) & "', " &
"'" & pp.Picture & "', " &
"'" & pp.AddedDate & "', " &
"'" & ReplaceApostrophes(pp.AddedBy) & "')
the pp.Picture is the Byte(). The error i'm getting is:
Operator '&' is not defined for types 'String' and 'Byte()'
i have googled around but cannot find anything. Does anyone have any idea how to correct this? or is there a better way to write the SQL statement? If i can't get this to work the network team said i can use the server file method but they are really pushing the blob in SQL storage instead. Thanks in advance.
Always use Parameters to avoid sql injection, make you sql statement easier to write and read, and make sure you are sending the correct datatypes. Parameters will also allow apostrophes. Use the .Add method. 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
In the code below, I had to guess at the SqlDbType and Size. Check your database for the correct information.
Connections and commands are using unmanaged resources. They release these resources in their .Dispose method so this method must be called. Using...End Using blocks take care of closing and disposing objects even if there is an error.
I assumed pp was an instance of a class. I gave the class the name Person. Correct this to the real class name.
Private ConStr As String = "Your connection string"
Private Sub InsertAuthAccessID(pp As Person)
Dim sql = "INSERT INTO AuthAccessID (
FName,
MName,
LName,
Suffix,
Address,
AddressExt,
City,
State,
Zip,
LawFirm,
Picture,
AddedDate,
AddedBy)
VALUES (
#FName,
#MName,
#LName,
#Suffix,
#Address,
#AddressExt,
#City,
#State,
#Zip,
#LawFirm,
#Picture,
#AddedDate,
#AddedBy)"
Using cn As New SqlConnection(ConStr),
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("#FName", SqlDbType.VarChar, 50).Value = pp.FName
cmd.Parameters.Add("#MName", SqlDbType.VarChar, 50).Value = pp.MName
cmd.Parameters.Add("#LName", SqlDbType.VarChar, 100).Value = pp.LName
cmd.Parameters.Add("#Suffix", SqlDbType.VarChar, 20).Value = pp.Suffix
cmd.Parameters.Add("#Address", SqlDbType.VarChar, 200).Value = pp.Address
cmd.Parameters.Add("#AddressExt", SqlDbType.VarChar, 50).Value = pp.AddressExt
cmd.Parameters.Add("#City", SqlDbType.VarChar, 100).Value = pp.City
cmd.Parameters.Add("#State", SqlDbType.VarChar, 50).Value = pp.State
cmd.Parameters.Add("#Zip", SqlDbType.VarChar, 20).Value = pp.Zip
cmd.Parameters.Add("#LawFirm", SqlDbType.VarChar, 200).Value = pp.LawFirm
cmd.Parameters.Add("#Picture", SqlDbType.VarBinary).Value = pp.Picture
cmd.Parameters.Add("#AddedDate", SqlDbType.Date).Value = pp.AddedDate
cmd.Parameters.Add("#AddedBy", SqlDbType.VarChar, 50).Value = pp.AddedBy
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
EDIT:
In older versions of VB that did not support multiline String literals, you can use an XML literal instead:
Dim sql = <sql>
INSERT INTO AuthAccessID (
FName,
MName,
LName,
Suffix,
Address,
AddressExt,
City,
State,
Zip,
LawFirm,
Picture,
AddedDate,
AddedBy)
VALUES (
#FName,
#MName,
#LName,
#Suffix,
#Address,
#AddressExt,
#City,
#State,
#Zip,
#LawFirm,
#Picture,
#AddedDate,
#AddedBy)
</sql>
Using cn As New SqlConnection(ConStr),
cmd As New SqlCommand(sql.Value, cn)
Too long and involved for a comment. You have the following snippet in your code:
")" &
"VALUES(" &
"" & ReplaceApostrophes(pp.FName) & ", " &
"'" & ReplaceApostrophes(pp.MName) & "', " &
That is an error. FName is a string and must be treated in exactly the same manner as you do with MName. It is missing the single quote delimiters.
More generally, this approach relies on converting all your "fields" into literals to embed them as strings within your tsql statement. So the question now becomes how do you "write" a binary literal in tsql. You would do that by generating a string like this: 0x69048AEFDD010E. Documentation for tsql constants is here. Knowing that, the next issue is how to do that in your dev language - which is not something I can answer. This look promising.
But before you go down this path, use parameterization and you NEVER have to deal with this ever again.
I come from a MSAccess background, so I code quite much the same way I did in VBA or now with VB.net
Here the code I would use:
Dim sFields() As String
sFields = Split("FName,MName,LName,Suffix,Address,AddressExt,City,State,Zip,LawFirm,AddedDate,AddedBy", ",")
Dim rst As DataTable
Dim da As SqlDataAdapter
rst = MyrstEdit("select * from AuthAccessID where id = 0", da, strcon)
With rst.Rows.Add
For Each s In sFields
.Item(s) = GetValue(pp, s)
Next
End With
da.Update(rst)
And I have two helper routines. The first one gets any class property by a "string" value.
Since by luck, you have field names and the class members are the same!
Public Function GetValue(ByRef parent As Object, ByVal fieldName As String) As Object
Dim field As FieldInfo = parent.[GetType]().GetField(fieldName, BindingFlags.[Public] Or BindingFlags.Instance)
Return field.GetValue(parent)
End Function
And then I have a datable routine - that gets me the data table, and is this:
Public Function MyrstEdit(strSQL As String, ByRef oReader As SqlDataAdapter) As DataTable
Dim mycon As New SqlConnection(strCon)
oReader = New SqlDataAdapter(strSQL, mycon)
Dim rstData As New DataTable
Dim cmdBuilder = New SqlCommandBuilder(oReader)
Try
oReader.Fill(rstData)
oReader.AcceptChangesDuringUpdate = True
Catch
End Try
Return rstData
End Function
So, to get all the data types and structure? I pass a dummy sql that returns no rows. (no rows are returned, but we DO GET the valuable table data types when we do this dummy table pull!). In most cases, if the PK is a autonumber, then I use id = 0.
that same MyRstEdit() code bit has tons of uses! You can now deal with a table in a nice structure, loop it, shove it into a combo box, or datagrid. And as it shows, also allows editing of the data - all with type checking.
The REAL trick and tip I am sharing here? Break out your common data routines to about 2-3 routines like MyRstEdit().
That way, you really don't have to deal with messy in-line sql, or every time you need to work on a table, you don't wire truckloads of code. And the real beauty here is that data typing is done for you - you don't have line after line of parameters, nor line after line of data typing for each column.
So, I hope this post gives you some ideas. But it also nice since I get to code much like I did in MSAccess, and that includes writing VERY little code for updates such as this.
The ideas here are just that - a different approach. The other approaches here are also just fine. (but are quite a bit more code then I perfer).
There are times when using a data table is a rather nice - and I think this is such an example.
And while I am oh so often used to referencing columns as a table collection? The cool trick here is I am also referencing each member of the class with a string too!
I got some strings that contains a single quote (') like Mayor's Office:
Dim Str = "Insert into EntryTbl(Office, DateCreated, TimeCreated)" & _
"Values('" & OfficeBox.Text & "', " & _
" '" & Now.ToShortDateString & "', " & _
" '" & Now.ToString("HH:mm:ss") & "')"
and the officebox.text contains a string Mayor's Office
Glad for any help :)
IMO, parametrized query is better because it prevents SQL injection and it will handle escaping for you(no need to write additional method to handle escaping)
Dim cmd As New SqlCommand("", Conn())
With cmd
.CommandText = "Insert into tbl(Office, DateCreated, TimeCreated)" & _
"Values(#office,#DateCreated,#TimeCreated)"
.Parameters.AddWithValue("#office", OfficeBox.Text)
.Parameters.AddWithValue("#DateCreated", Now.ToShortDateString)
.Parameters.AddWithValue("#TimeCreated", Now.ToString("HH:mm:ss"))
.ExecuteNonQuery()
End With
Take a look at How do I create a parameterized SQL query? Why Should I? for more informations
The built in solution is to use
QUOTENAME(#string)
function to put the quotes.
Why am I getting this error
Syntax error INSERT INTO statement
Please help! Thanks in advance!
Dim cmd As New OleDb.OleDbCommand
If TabControl1.SelectedIndex = 0 Then
If Not cnn.State = ConnectionState.Open Then
'open connection if it is not yet open
cnn.Open()
End If
cmd.Connection = cnn
'check whether add new or update
If Me.txtStdID.Tag & "" = "" Then
'add new
'add data to table
cmd.CommandText = "INSERT INTO Student (StudentID, LastName, FirstName, MiddleInitial, Grade, Section, ContactNumber, AdviserID, CounselorID, ParentName)" & _
"VALUES('" & Me.txtStdID.Text & "','" & Me.txtLname.Text & "','" & _
Me.txtFname.Text & "','" & Me.txtMidInt.Text & "','" & _
Me.txtGrade.Text & "','" & Me.txtSection.Text & "','" & Me.txtContact.Text & "','" & _
Me.txtAdvID.Text & "','" & Me.txtConID.Text & "','" & Me.txtPname.Text & "')"
cmd.ExecuteNonQuery()
Well, this is a well known problem. Databases define many words as "reserved keywords", and if they are used for column names or table names, they need to be enclosed in the appropriate quoting character for your database.
Seeing that you are using an OleDbConnection I assume that you are using MS-Access as database. In that case the list of reserved keywords could be found here,
And indeed SECTION is a reserved keyword, so your query, should be written as
"INSERT INTO Student (......, [Section], ......
Said that, let's say something about string concatenation to build an SQL Query.
It's bad, bad, bad.... There are numerous problem with that. For example, what happens if one of your fields contains a single quote? The whole query will fail again with a Syntax error. Also, albeit more difficult to exploit with Access because it doesn't support multiple command texts there is the problem of SQL Injection to avoid at all costs. You need to learn how to use a PARAMETERIZED QUERY
Dim sqlText = "INSERT INTO Student (StudentID, LastName, FirstName, " & _
"MiddleInitial, Grade, [Section], ContactNumber, AdviserID, " & _
"CounselorID, ParentName) VALUES (?,?,?,?,?,?,?,?,?,?)"
If TabControl1.SelectedIndex = 0 Then
Using cnn = New OleDbConnection(...constring here....)
Using cmd = new OleDbCommand(sqlText, cnn)
cnn.Open()
cmd.Parameters.Add("#p1", OleDbType.VarWChar).Value = Me.txtStdID.Text
cmd.Parameters.Add("#p2", OleDbType.VarWChar).Value = Me.txtLname.Text
.... and so on with the other parameters ....
.... strictly following the order of the fields in the insert....
cmd.ExecuteNonQuery()
End Using
End Using
VB.net access update query is giving a Syntax Error in Update Query Error. My query is as follows:
query = "UPDATE users SET username='" & newUsername & "', password='" & newPassword & "', department='" & newDepartment & "', display_name='" & newDisplayName & "', email='" & newEmail & "', extension='" & newExtension & "', access_level='" & newAccessLevel & "' WHERE id=" & usrID
None of the above variables have any symbols at all. What am I doing wrong?
::UPDATE::
UPDATE users SET username='alison', password='farm1234',department='1',display_name='Alison *****', email='production#**********.com', extension='1012',access_level='50' WHERE id=1
This is what the query runs as.
The error is caused by the usage of the reserved keyword PASSWORD without enclosing it in square brackets.
Said that, you never use string concatenation to build sql commands, but always a parameterized query to avoid Sql Injection problems but also syntax error in parsing text values (containing single quotes) or decimal values with their decimal separators or dates values.
So, a possible approach to your task could be
query = "UPDATE users SET username=?, [password]=?, department=?, " & _
"display_name=?, email=?, extension=?, access_level=?" & _
" WHERE id=?"
Using cmd = new OleDbCommand(query, connection)
cmd.Parameters.AddWithValue("#p1", newUsername)
cmd.Parameters.AddWithValue("#p2", newPassword)
cmd.Parameters.AddWithValue("#p3", newDepartment)
cmd.Parameters.AddWithValue("#p4", newDisplayName)
cmd.Parameters.AddWithValue("#p5", newEmail)
cmd.Parameters.AddWithValue("#p6", newExtension)
cmd.Parameters.AddWithValue("#p7", newAccessLevel)
cmd.Parameters.AddWithValue("#p8", usrID)
cmd.ExecuteNonQuery()
End Using
Keep in mind that OleDb doesn't use the parameter names to find the corresponding placeholder in sql command text. Instead it uses a positional progression and thus adding the parameters to the collection should respect the order in which the parameter appears in the sql command text
ConStr()
Qry="UPDATE users SET username=#uname, [password]=#pass, department=#dept, " & _
"display_name=#dnam, email=#email, extension=#ext, access_level=#acslvl" & _
" WHERE id=#id"
cmd = new oledbcommand(Qry,Conn)
cmd.Parameters.AddWithValue("#uname",newUsername)
cmd.Parameters.AddWithValue("#pass",newPassword)
cmd.Parameters.AddWithValue("#dept",newDepartment)
cmd.Parameters.AddWithValue("#dnam",newDisplayName)
cmd.Parameters.AddWithValue("#email",newEmail)
cmd.Parameters.AddWithValue("#ext",newExtension)
cmd.Parameters.AddWithValue("#acslvl",newAccessLevel)
cmd.Parameters.AddWithValue("#id",usrID)
cmd.ExecuteNonQuery()
My objective is to input all checked items from a checkbooxlist into a single column in my database.
I understand it is not a good design. However, this is the requirement.
Here is the code I use to get all the selected items from checkboxlist:
Dim listitems As String
listitems = ControlChars.CrLf
For i = 0 To (chkActivities.Items.Count - 1)
If chkActivities.GetItemChecked(i) = True Then
listitems = listitems & (i + 1).ToString & chkActivities.Items(i).ToString & ControlChars.CrLf
End If
Next
Here is the connection string and command executed to populate my table:
>
objCon.Open()
objCmd = New SqlCommand("insert into activity_by_customer (userID, city, personal_activities, BookingDate, price) values ( '" & frmLogin.userID & "','" & cbbCity.Text & "','" & listitems & "','" & Date.Today & "','" & lblpriceValue.Text & "' )", objCon)
objCmd.ExecuteNonQuery()
activitiesbycustomer.Update(Me.ResourcesDataSet.activity_by_customer)
MsgBox("Your booking has been successful")
objCon.Close()
However when I execute this code it crashes with an error. The error is as follows:
Incorrect syntax near 's'.
Unclosed quotation mark after the character string ' )'.
This error happens to appear because of 'listitems'.
Any help would be appreciated.
Not a problem in how you build your listitems, but in how you pass the values to the database.
Do not use string concatenation to build a sql command
objCon.Open()
objCmd = New SqlCommand("insert into activity_by_customer " & _
"(userID, city, personal_activities, BookingDate, price) " & _
"values (#usrID, #city, #itms, #dt, #price)", objCon)
objCmd.Parameters.AddWithValue("#usrID",frmLogin.userID)
objCmd.Parameters.AddWithValue("#city",cbbCity.Text)
objCmd.Parameters.AddWithValue("#itms", listitems)
objCmd.Parameters.AddWithValue("#dt",Date.Today)
objCmd.Parameters.AddWithValue("#price", lblpriceValue.Text)
objCmd.ExecuteNonQuery()
....
In this way, the framework code formats your values considering the presence of characters like a single quote and avoiding the consequent syntax error. Moreover, in this way you avoid Sql Injection attacks