如何在sqlite和c#中解决"'"问题?

6

我正在使用Microsoft Visual C# 2008 Express和Sqlite进行工作。

我知道在我的文本中使用撇号(')会导致查询出现问题。我的问题是,我认为我可以用\'来替换它,但似乎并没有起作用...以下是我代码的简化示例:

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

我收到的错误信息是: SQLite 错误: 附近有“t”的语法错误
我尝试了几个替换方法...比如使用另一个斜杠。 我将我的字符串及其替换后的版本写出来,以确保它正确输出。
在这里我可能犯了什么愚蠢的错误?
谢谢!
-Adeena
2个回答

18

Robert提出的解决方法是可行的(即用''代替')。

或者你可以使用参数,如:

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();

2
使用参数是个好习惯。Robert的解决方案当然可行,但使用参数也有助于防止SQL注入攻击。 - Scott Ferguson
那么将输入中的 ' 替换为 '' 也可以。 - Blindy

7
使用参数可以防止SQL注入,并且使问题消失。这也更加快速,因为当您使用参数时,SQLite可以重用语句的执行计划。如果不使用参数,则无法重用。在此示例中,使用参数使批量插入操作快了约3倍。
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();
  }
}

在使用参数化 SQL 语句时,Sqlite 的行为与 Oracle 相似。


同意。这绝对是更好的答案。 - Raymond Hettinger
当您使用“using”时,是否有必要调用conn.Close()?我被告知这是多余的。 - B. Clay Shannon-B. Crow Raven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接