我发布了一个我之前遇到过的另一个问题,并通过一些帮助解决了这个问题。
我现在收到以下代码为中心的语法错误:
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();
这是输出:
使用断点我已确定导出阅读器调用正在接收数据。我已将其缩小到以下问题:
"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)))
这没有问题,所以我知道问题不在于底层连接或命令。
答案 0 :(得分:3)
其他正确评论SQL注入,但VFP对SQL注入的影响较小,它可以是相同的。主要原因,VFP并不真正使用多个查询,就像其他sql引擎允许的那样“;”识别语句之间的中断。但是,如果引号不匹配,则CAN和WILL会破坏实际运行的sql语句。
话虽如此,VFP OleDb提供程序确实允许参数化,但没有“命名”参数。它用“?”做到了作为.net框架将插入值的占位符,只要它具有相同的预期格式(例如:字符串,数字,日期),就不必转换数据类型
将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,insert或delete)的相应字段的参数位置。命令对象对所有命令的工作方式相同。即使你编写了一个select语句,并且在WHERE,JOIN或其他任何位置都有值。
那么,ExecuteNonQuery()
答案 1 :(得分:1)
您的代码的修订版将是:
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 [“...”]。值= ...但是你只能在单个插入时这样做(不是与VFP相关的东西,就是OleDb或Sql或其他什么东西)。
答案 2 :(得分:0)
您不需要ExecuteReader
来插入声明。只需使用ExecuteNonQuery
。
在您的情况下,如果您的列是字符类型,则需要使用单引号;例如
VALUES ('{0}', '{1}', '{2}')
在VALUES
部分之前也使用空白区域(不必,但作为良好做法)。
"INSERT INTO CLIENT (Title,Fname,Sname)" + " VALUES (Mr,Joshua,Cameron-Mackintosh)",
// ^^^ here
您应始终使用parameterized queries。例如,Prepared语句自动处理转义字符,并且这种字符串连接对SQL Injection攻击是开放的。
答案 3 :(得分:0)
您必须为连接的字符串留出空间。
"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