2

I am having a problem with inserting new data into MS Access 2007 file. It say I am having an incorrect SQL statement.

What is the problem here? I am not good at SQL. Please point out my error.

            try
            {
                // Open database connection.
                objOleDbConnection.Open();
                objOleDbCommand.CommandText = 
                    "INSERT INTO PersonalData (Type, UserName, Password) VALUES ('" + cmbType.Text + "','" + txtUserName.Text + "','" + txtPassword.Text + "')";
                // Execute creating table command.
                objOleDbCommand.ExecuteNonQuery();
            }

4 Answers 4

5

To start with, you need to put quotes around your text data:

@"INSERT INTO PersonalData (Type, UserName, Password) VALUES (" + cmbType.SelectedIndex + ",'" + txtUserName.Text + "','" + txtPassword.Text + "')";

However, you would be much better off converting this to use parameters, since you won't have to worry about embedded quotes:

objOleDbCommand.CommandText = @"INSERT INTO PersonalData (Type, UserName, Password) VALUES (?, ?, ?)";

objOleDbCommand.Parameters.Add("Type", cmbType.SelectedIndex); 
objOleDbCommand.Parameters.Add("UserName", txtUserName.Text);
objOleDbCommand.Parameters.Add("Password", txtPassword.Text);
Sign up to request clarification or add additional context in comments.

2 Comments

Does either your user name or password have single quotes (') in it?
For clarification. Those question marks are just a placeholder or should I substitute them as a variable names?
4

Both Type and Password are reserved words. See Problem names and reserved words in Access.

If you must keep those as the field names, surround them with square brackets in your INSERT statement so the database engine will know to interpret them as fields:

"INSERT INTO PersonalData ([Type], UserName, [Password]) VALUES ...

On that same web page, follow the link for Database Issue Checker Utility. That utility can warn you about problems with reserved words in your application, and other potential troublesome issues.

Edit: If PersonalData includes additional fields which are required and do not have default values assigned, you must include those fields with values in your INSERT statement, or it will definitely fail.

4 Comments

Thank you! This is it. I had no idea that some words might be reserved words.
HansUp Posted as I was finishing. Apologies for the redundancy re: Keywords. You really SHOULD check out parameterized SQL though.
@XIVSolutions Paremeter approach had already been mentioned, so I didn't repeat that. And although good advice, I didn't believe it would solve the underlying problem.
You did solve my original problem first, so you do deserve answer points.
3

Let's say txtUserName.Text is Foo, and txtPassword.Text is bar. Then you're getting

INSERT INTO PersonalData (Type, UserName, Password) VALUES (3,foo,bar)

instead of the syntactically correct

INSERT INTO PersonalData (Type, UserName, Password) VALUES (3,'foo','bar')

Since you don't have columns foo and bar, you are getting an error - is my assumption. Things get worse if you have baz,moo instead of foo. Or, gods forbid, Bobby Tables.

3 Comments

Ok, I have tried that but I am still having the same problem. Plus, thanks for pointing out my error. I meant the type to be a string also, not a number :)
What error are you getting anyway? (BTW, I'm not an Access guy, all I wrote is general SQL)
A good idea is to print out your SQL statement before you try to execute it - it might show you more clearly what you're actually sending to the engine. Can you paste a objOleDbCommand.CommandText that you are getting the error on?
3

There a few places where you might encounter problems here.

  1. Type, Username, and Password are all (I think) MS Access keywords. While they seem to work when used within Access istself (like in the Querybuilder, for example), they seem to throw exceptions when used from Client Code. Surround the fieldnames in your SQL Statement with square brackets, so that Access treats them as literals.

  2. I strongly recommend using SQL Parameters for your in-line SQL, and then using ADO.NET Parameters to set the values. Google "SQL Injection Attack" to learn why. Plus, it's just good practive (there are some limited exceptions).

EDIT: Note that with OleDb, the parameters must appear in the same order as the fliednames in the list. THis is not the case with ADO & SQLClient. With Access, however, having your parameters out of order will create difficult-to-find problems . . .

Your SQL would then look like this:

INSERT INTO ([Type], [Username], [Password]) VALUES ( @Type, @UserName, @Password )

And your code might resemble THIS (I took some liberties here . . .

private void InsertUserData(int Type, String UserName, String Password)
{
    // The "Using" block handles object creation and disposal - 
    // handy for unmanaged resources like database connections:
    using(OleDbConnection cn = new OleDbConnection(YourConnectionString))
    {
        using(OleDbCommand cmd = new OleDbCommand())
        {
            cmd.Connection = cn;

            // 1.  Note the use of Parameters here. This will hinder attempts to 
            // compromise your app with SQl Injection and/or faulty user input. 

            // 2. Also note that, since "Type", "Username", and "Password" are all 
            // MS Access keywords, there is a potential for problems when 
            // used as fieldnames. Therefore we enclose them 
            // in square brackets [] in the "INSERT INTO" Clause:
            String SQL =
                "INSERT INTO PersonalData([Type], [UserName], [Password]) " +
                "VALUES(@Type, @UserName, @Password)";

            // Set the CommandText Proprty:
            cmd.CommandText = SQL;

            // Now create some OleDb Parameters:
            OleDbParameter prmType = new OleDbParameter("@Type", Type);
            OleDbParameter prmUserName = new OleDbParameter("@UserName", UserName);
            OleDbParameter prmPassword = new OleDbParameter("@Password", Password);

            // Add the params to the parameters collection:
            cmd.Parameters.Add(prmType);
            cmd.Parameters.Add(prmUserName);
            cmd.Parameters.Add(prmPassword);

            try
            {
                cn.Open();
                cmd.ExecuteNonQuery();
                cn.Close();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

Hope that helps . . .

3 Comments

Good point. I have not know that there might be some security issues there.
One more thing. Is there any difference to close the connection in try/finally block?
No, closing in the finally block is fine. Probably better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.