Answered by:
Error in syntax INSERT INTO

Question
-
When I use this code, it gives me this error: Syntax error in INSERT INTO statement.
protected void Button1_Click(object sender, EventArgs e) { using (OleDbConnection conn = new OleDbConnection()) { conn.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\\AIRSIGNDMC\AirSign Server\AirSignProgramming\AirSignDatabase.accdb"; string sql = string.Format("INSERT INTO Events(EventName, Date/Time, Location, Notes, Clients) VALUES('{0}','{1}','{2}','{3}','{4}')", TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text, TextBox5.Text); using (OleDbCommand cmd = new OleDbCommand(sql, conn)) { try { conn.Open(); cmd.ExecuteNonQuery(); } finally { conn.Close(); } conn.Close(); { GridView1.DataSource = null; GridView1.DataBind(); } }
But when I use this (in the place of the code that is in bold)
"INSERT INTO Events(EventName, Location, Notes) VALUES('{0}','{1}','{2}')", TextBox1.Text, TextBox2.Text, TextBox3.Text);
it works fine. As you can see, the only thing changed is the number or columns data inserted to. everything in my access database is set as "Text" except "Clients" which is a hyperlink.
Answers
-
Date/Time is not valid column syntax. If you have a column with that name then you need to escape it as: [Date/Time].
Michael Taylor - 8/3/2012
http://msmvps.com/blogs/p3net
- Proposed as answer by datAdrenalineMVP Sunday, August 5, 2012 2:16 AM
- Marked as answer by Jason Dot Wang Monday, August 13, 2012 8:48 AM
-
Like this?
"INSERT INTO Events(EventName, [Date/Time], Location, Notes) VALUES('{0}','{1}','{2}','{3}','{4}')", TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text, TextBox5.Text);
- Proposed as answer by Jason Dot Wang Tuesday, August 7, 2012 2:35 AM
- Marked as answer by Jason Dot Wang Monday, August 13, 2012 8:48 AM
All replies
-
Date/Time is not valid column syntax. If you have a column with that name then you need to escape it as: [Date/Time].
Michael Taylor - 8/3/2012
http://msmvps.com/blogs/p3net
- Proposed as answer by datAdrenalineMVP Sunday, August 5, 2012 2:16 AM
- Marked as answer by Jason Dot Wang Monday, August 13, 2012 8:48 AM
-
Like this?
"INSERT INTO Events(EventName, [Date/Time], Location, Notes) VALUES('{0}','{1}','{2}','{3}','{4}')", TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text, TextBox5.Text);
- Proposed as answer by Jason Dot Wang Tuesday, August 7, 2012 2:35 AM
- Marked as answer by Jason Dot Wang Monday, August 13, 2012 8:48 AM
-
-
-
-
An additional point: it is not only preferable to surround string values with quotes but also to ensure that the text cannot close quote itself.
If a user enter in TextBox1:
',' ',' '); DELETE Events; INSERT INTO Events(EventName, [Date/Time], Location, Notes) VALUES('
all the Events are deleted.
So I deeply suggest you to have a SqlString(string s, bool nullable=false) method that returns s surrounded with quotes with each simple quote in s doubled to protect you from SQL code injection and to have similar SqlInt32, SqlDateTime, SqlBool ... that also prevent SQL code injection and can handle null value when they are authorized.
-
Actually, the proper way to prevent against SQL injection is to use Parameters:
string sql = "INSERT INTO Events(EventName, [Date/Time], Location, Notes, Clients) VALUES(?, ?, ?, ?, ?)"; using (OleDbCommand cmd = new OleDbCommand(sql, conn)) { try { cmd.Parameters.AddWithValue("EventName", TextBox1.Text); cmd.Parameters.AddWithValue("Date", TextBox2.Text); cmd.Parameters.AddWithValue("Location", TextBox3.Text); cmd.Parameters.AddWithValue("Notes", TextBox4.Text); cmd.Parameters.AddWithValue("Clients", TextBox5.Text); conn.Open(); cmd.ExecuteNonQuery(); } // etc.etc. with the catch }
Note that the parameters in an Access database are positional rather than named (like in SQL Server), so even though you give the parameters names when adding them, it's really the order that they're in that are important.~~Bonnie Berent DeWitt [C# MVP]
geek-goddess-bonnie.blogspot.com -
>> SQL injection <<
It is important to note that the Jet/ACE database engine will not do two "things" at once, so SQL Injection of a DELETE sql statement inside of a SELECT sql statement will be ineffective. The only time I have seen successful SQL injection with queries passed to a Jet/ACE database is in the WHERE clause, something like ...
userInput: ' Or [someTextField] = 'brent' & '
strSQL = "SELECT * FROM someTable WHERE someTextField = '" & userInput & "'"
With that, the sql statement will resolve to ...
SELECT * FROM someTable WHERE someTextField = '' Or [someTextField] = 'brent' & ''
Which is completely valid. But adding a DELETE or INSERT will not be accepted by Jet/ACE.
------
>> parameters in an Access database are positional rather than named <<
You can use either named or positional, but that is a benefit of the OleDb provider, not Access (Jet/ACE). You an use positional parameters with SQL Server as well, if you are using the OleDb provider.
Brent Spaulding | Access MVP
-
It is important to note that the Jet/ACE database engine will not do two "things" at once, so SQL Injection of a DELETE sql statement inside of a SELECT sql statement will be ineffective
Still, don't you agree that using parameters is the preferable methodology?
You can use either named or positional, but that is a benefit of the OleDb provider, not Access (Jet/ACE). You an use positional parameters with SQL Server as well, if you are using the OleDb provider.
It's funny ... I started to write OleDb rather than Access ... I guess I should have stayed with my initial thought. And thanks for catching that, Brent. But who, in their right mind, would use the OleDb provider for SQL Server? ;0)
~~Bonnie Berent DeWitt [C# MVP]
geek-goddess-bonnie.blogspot.com -
>> Still, don't you agree that using parameters is the preferable methodology? <<
I will answer with an "It depends" :) ... If my parameters are coming from internal data (ie: not a user input), or if the user input value is numeric, I will append text because of the low risk. When I have a Jet/ACE backend, I append text all the time, even if the user input is to be text.
In short, I evaluate the risk of not using parameters in conjuction with what I am doing. But keep in mind that I develop internal buisness apps/dlls/pages, which is different than developing shrink wrapped apps or providing code per a spec (ie: contracted to write a method, so you don't know the whole scope). I personally find it to be pain to go through the motions (code) to add parameters, especially if the number of parameters can against the same core SQL statement -- like when building a search dialog that can accept many values against many columns.
With that said, and with a general or unknown scope, audience, etc. -- I concede that using parameters would be preferrable, in addition, that practice is sometimes forced by a client or departmental code style. So, if I were teaching a class, I would imagine the text book answer and a lecture topic would be to use parameters, but in practice, I evaluate the risk and most of the time I will append text to build a literal SQL statement.
>> But who, in their right mind, would use the OleDb provider for SQL Server? ;0) <<
While I agree, there are scenario's in which I would use the generic OleDb classes --- if you want the back end to be not be bound to a particular engine. For example, I just worked on an app that could use Jet/ACE, SQL Server, MySQL, or ?? as the back end format. I used the Odbc namespace (instead of OleDb) in order to ensure my back end was independant of a engine.
>> I guess I should have stayed with my initial thought. <<
"They" (who ever that is) always say to go with your first thought --- or answer "C" as it is the most probable correct answer :)
Brent Spaulding | Access MVP
-
Still, don't you agree that using parameters is the preferable methodology?
In my mind using the OleDbCommand.Parameters is very verbose and memory allocation intensive only to construct a string request and was designed with code generator in mind more than for a human writer. I never explored the potential recycling of OleDbCommands in multithreading environment. Two reason why a prefer using easy to write and use SqlChar, SqlInt methods to construct request parameters.
-
I use a DataAccess class that I've written. The methods I wrote makes it easy enough to add parameters, no need for any versosity. That particular class is targeted to SQL Server.
But at a company where I used to work, I wrote a good part of the framework we used and we had a DataAccess base class that was written to the IDb interfaces, so it could easily be used with other databases. Notice I said it was a base class. We then could sub-class it to target different database providers if necessary. It never became necessary, we only used SQL Server so we only had the one sub-class, but the flexibility was there in case we needed it.
~~Bonnie Berent DeWitt [C# MVP]
geek-goddess-bonnie.blogspot.com