views:

1359

answers:

4

I'm working in Microsoft Visual C# 2008 Express with Sqlite.

I understand that an apostrope (') in my text has problems in a query. My problem is that I thought I could replace it with \'. It doesn't seem to be working... Here's a parred down example of my code:

string myString = "I can't believe it!";
cmd.CommandText = "Insert into myTable (myid,mytext) values (1,'" + myString.Replace("'","\\'") + "');";

The error I get is: SQLite error: near "t": syntax error

I've tried a couple other replacements... like the other slash. And I wrote my string and a replaced version of my string out to the console to make sure it was coming out right.

What stupid error am I making here?

Thanks!

-Adeena

+2  A: 

You have to use two apostrophes in a row to replace the apostrophe.

Robert Harvey
that was it. thank you! :)
adeena
The stupid error you are making is using this solution. This is prone to SQL injection, so use parameters. Granted, this answer answers your direct question, how to fix the problems of apostrophes. My comment here answers your second question "What stupid error am I making here?".
Lasse V. Karlsen
Use parameters, much faster, no ' problem and no sql injection!
tuinstoel
Folks, this is not an enterprise database. And if the app is not exposed to the internet, you're not going have issues with SQL injection. Quit making this a religion
Robert Harvey
How do you know it will not become an enterprise database? Anyway performance is also an important reason to use parameters.
tuinstoel
*sigh* If it becomes an enterprise database, it will most likely no longer be using SQLite.
Robert Harvey
..."sigh ... no longer be SQLite"... If you start with parameters porting to MS SQL, MySQL or Oracle will be easier. MSSQL, MySQL and Oracle are all vulnerable to SQL injection attacks.
tuinstoel
+13  A: 

The solution presented by Robert will work (i.e. replacing ' by '').

Alternatively you can use parameters as in:

DbCommand   cmd = new DbCommand();
DbParameter param = cmd.CreateParameter();
// ...
// more code
// ...
cmd.CommandText = "Insert table (field) values (@param)";
param.ParameterName = "param"
param.DbType = DbType.String;
param.Value  = @"This is a sample value with a single quote like this: '";
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
Paulo Santos
+1 for using parameters. Robert's solution will work of course, but using parameters will help protect against SQL Injection attacks too.
Scott Ferguson
So will replacing ' in the input with '' tho.
Blindy
+1  A: 

Agree with Robert's comment... you are WIDE OPEN for SQL Injection... just to test what COULD happen, try something like this for input text and see what happens to your table content (or actually, create a bogus table with a few records and try against that...

textbox entry has "; truncate table myTable"

The semi-colon terminates the prior instruction, and can then run the next which in this case, would delete all records in your table...

Although simple in its context, any SQL WITHOUT using parameters is dangerous..

DRapp
Thanks! I definitely get the message that parameters are important... really, I do. That will be one of the next steps - I need to build up to that. :) I'm still learning A LOT as I work on this project... and can only handle so much new stuff per day. :) :)
adeena
+3  A: 

Using parameters protects against sql injection, and makes the ' problems qo away.

It is also much faster because sqlite can reuse the execution plan of statements when you use parameters. It can't when you don't use parameters. In this example using a parameter makes the bulk insert action approximately 3 times faster.

private void TestInsertPerformance() {
  const int limit = 100000;
  using (SQLiteConnection conn = new SQLiteConnection(@"Data Source=c:\testperf.db")) {
    conn.Open();
    using (SQLiteCommand comm = new SQLiteCommand()) {
      comm.Connection = conn;
      comm.CommandText = " create table test (n integer) ";
      comm.ExecuteNonQuery();
      Stopwatch s = new Stopwatch();
      s.Start();
      using (SQLiteTransaction tran = conn.BeginTransaction()) {
        for (int i = 0; i < limit; i++) {
          comm.CommandText = "insert into test values (" + i.ToString() + ")";
          comm.ExecuteNonQuery();
        }
        tran.Commit();
      }
      s.Stop();
      MessageBox.Show("time without parm " + s.ElapsedMilliseconds.ToString());

      SQLiteParameter parm = comm.CreateParameter();
      comm.CommandText = "insert into test values (?)";
      comm.Parameters.Add(parm);
      s.Reset();
      s.Start();
      using (SQLiteTransaction tran = conn.BeginTransaction()) {
        for (int i = 0; i < limit; i++) {
          parm.Value = i;
          comm.ExecuteNonQuery();
        }
        tran.Commit();
      }
      s.Stop();
      MessageBox.Show("time with parm " + s.ElapsedMilliseconds.ToString());

    }
    conn.Close();
  }
}

Sqlite behaves similar to Oracle when it comes to the importance of using parameterised sql statements.

tuinstoel