是什么导致了这个语法错误? oledb 插入语句

What's causing this syntax error? oledb INSERT statement

我发布了我之前遇到的另一个问题,并在一些帮助下解决了这个问题。

我现在收到围绕以下代码的语法错误:

importConnection.Open();
Console.WriteLine("Foxpro connection open");
OleDbCommand deleteOleDbCommand = new OleDbCommand(@"TRUNCATE TABLE CLIENT",
                            importConnection);

Console.WriteLine("writing to table");
Console.ReadKey();
using (OleDbCommand importCommand = new OleDbCommand(
    string.Format("INSERT INTO CLIENT (Title,Fname,Sname)" + "VALUES ({0},{1},{2})",
    exportReader.GetValue(0), exportReader.GetValue(1), exportReader.GetValue(2))))
    importCommand.ExecuteReader();

这是输出:

Output Text

使用断点我确定导出 reader 调用正在接收数据。我已将其缩小为以下问题:

"VALUES ({0},{1},{2})",
  exportReader.GetValue(0), exportReader.GetValue(1), exportReader.GetValue(2))))

我已确认可以通过执行以下操作插入数据:

using (OleDbCommand importCommand =
    new OleDbCommand(string.Format(
       "INSERT INTO CLIENT (Title,Fname,Sname)" + "VALUES (Mr,Joshua,Cameron-Mackintosh)",
           importConnection)))

这不会导致任何问题,所以我知道问题不在于底层连接或命令。

插入语句不需要 ExecuteReader。只需使用 ExecuteNonQuery.

在你的例子中,如果你的列是字符类型的,你需要使用单引号;

VALUES ('{0}', '{1}', '{2}')

VALUES 部分之前也使用白色 space(不是必须,但作为一个好的做法)。

"INSERT INTO CLIENT (Title,Fname,Sname)" + " VALUES (Mr,Joshua,Cameron-Mackintosh)",
                                       //  ^^^ here

但更重要;

你应该总是使用 parameterized queries. Prepared statements automatically handle for escape characters for example and this kind of string concatenations are open for SQL Injection 攻击。

你必须给你的串联字符串 space。

"INSERT INTO CLIENT (Title,Fname,Sname)" + "[space here]VALUES (Mr,Joshua,Cameron-Mackintosh)"

然而,它应该是这样的:

"INSERT INTO CLIENT (Title,Fname,Sname) VALUES (?,?,?)"

始终使用参数化查询。请参阅: http://blogs.technet.com/b/neilcar/archive/2008/05/21/sql-injection-mitigation-using-parameterized-queries.aspx

其他人对 SQL-Injection 的评论是正确的,但是 VFP 对 SQL-Injection 的影响较小,可能是一样的。主要原因是,VFP 并不像其他 sql 引擎通过“;”允许的那样真正处理多个查询。识别语句之间的中断。但是,如果引号不匹配,它可以并且将会破坏您的 sql-statements 实际上 运行.

话虽如此,VFP OleDb 提供程序确实允许参数化,但没有 "named" 参数。它用“?”来做作为 .net Framework 插入值的位置的占位符,并且您不必转换数据类型,只要它具有相同的预期格式(例如:字符串、数字、日期)

将您的 OleDbCommand 更改为

"INSERT INTO CLIENT (Title, Fname, Sname ) values ( ?, ?, ? )"

然后,通过

设置您的参数
importCommand.Parameters.Add( "parmForTitle", exportReader.GetValue(0));
importCommand.Parameters.Add( "parmForFName", exportReader.GetValue(1));
importCommand.Parameters.Add( "parmForSName", exportReader.GetValue(2));

此外,添加参数的顺序必须与它们在查询中出现的顺序完全相同。所以,我在它们前面加了前缀 "parmFor" 来表示它是相应字段被插入(或更新,或在 select 中使用,也插入或删除)的参数放置。命令对象对所有命令的作用相同。即使您编写了 select 语句并在 WHERE、JOIN 或任何其他位置具有值。

然后,ExecuteNonQuery()

  1. 那里说"foxpro connection string"。如果反对 VFP 数据库,那么 "Truncate table client" 将无法在 第一名。 VFP 中不存在该命令。相反,你可以 尝试使用 "Delete From Client" 来标记要删除的记录。 或者您可以将 "zap" 命令与 ExecSript 对应 "truncate table" 但是连接需要使用 table 独家.
  2. 您应该引用字符串值。更好的是,对于任何 SQL 操作,您都应该使用参数。当您使用参数时,您应该以正确的方式为您使用的连接执行此操作。这里你使用的是 OLEDB 连接,那么你应该使用 ?作为参数占位符。

您的代码的修订版本将是:

importConnection.Open();
Console.WriteLine("Foxpro connection open");
OleDbCommand deleteOleDbCommand = new OleDbCommand(@"Delete from CLIENT",
                            importConnection);

Console.WriteLine("writing to table");
Console.ReadKey();
using (OleDbCommand importCommand = new OleDbCommand(
    @"INSERT INTO CLIENT (Title,Fname,Sname) VALUES (?,?,?)",
    importConnection))
{
  importCommand.Parameters.AddWithValue("title","");
  importCommand.Parameters.AddWithValue("fname","");
  importCommand.Parameters.AddWithValue("sname","");

  // maybe in a loop here
  importCommand.Parameters["title"].Value = exportReader.GetValue(0);
  importCommand.Parameters["fname"].Value = exportReader.GetValue(1);
  importCommand.Parameters["sname"].Value = exportReader.GetValue(2);

  importCommand.ExecuteNonQuery();
  // ...
}

PS:您可以直接在 Parameters.AddWithValue 上提供值,而不是创建一个单独的 .Parameters["..."].Value = ... 但那样你只会能够为单个插入做到这一点(与 VFP 无关,OleDb 或 Sql 或其他任何东西都是这种情况)。