使用此 INSERT INTO 语句和 .NET OleDb 命名空间时如何解决语法错误?
Posted
技术标签:
【中文标题】使用此 INSERT INTO 语句和 .NET OleDb 命名空间时如何解决语法错误?【英文标题】:How to solve a syntax error when using this INSERT INTO statement and the .NET OleDb namespace? 【发布时间】:2011-01-07 16:13:24 【问题描述】:当我尝试将值插入 Access 数据库时,我不断收到错误消息。
错误是语法错误,导致如下异常:
OleDbException 是 INSERT INTO 语句中未处理的语法错误。
private OleDbConnection myCon;
public Form1()
InitializeComponent();
myCon = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\File.mdb");
private void insertuser_Click(object sender, EventArgs e)
OleDbCommand cmd = new OleDbCommand();
myCon.Open();
cmd.Connection = myCon;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO User ([UserID], [Forename], [Surname], " +
"[DateOfBirth], [TargetWeight], [TargetCalories], [Height]) " +
"VALUES ('" + userid.Text.ToString() + "' , '" +
fname.Text.ToString() + "' , '" +
sname.Text.ToString() + "' , '" +
dob.Text.ToString() + "' , '" +
tarweight.Text.ToString() + "' , '" +
tarcal.Text.ToString() + "' , '" +
height.Text.ToString() + "')";
cmd.ExecuteNonQuery();
myCon.Close();
【问题讨论】:
你能发布你收到的错误吗? 您遇到异常了吗?应用程序崩溃了吗?将语句括在 try..catch 块中,捕获异常并发布异常消息。 您好,这是异常消息:INSERT INTO 语句中的语法错误 OleDbException 未处理 我不会在 C# 中工作,所以不知道它如何与您的数据库接口层交互,但 Jet/ACE 使用#
作为日期值的字符串表示的分隔符,而不是'
。改变这可能会有所帮助。至少,写出正在发送的 SQL 字符串,看看是否可以在交互式 Access 中运行它。
【参考方案1】:
好吧,您还没有指定错误是什么 - 但您的第一个问题是您将数据直接插入到 SQL 语句中。 不要那样做。你是在邀请SQL injection attacks。
请改用parameterized SQL statement。完成此操作后,如果仍有问题,请使用新代码编辑此问题并说出错误是什么。新代码可能已经更清晰了,因为不会涉及大量串联,很容易隐藏不匹配括号之类的内容。
编辑:如 cmets 中所述,Jet/ACE 容易受到较少类型的 SQL 注入攻击,因为它不允许 DML。对于这个 INSERT 语句,实际上可能存在 no 漏洞 - 但对于以类似方式编写的带有 WHERE 子句的 SELECT,用户输入可能会绕过 WHERE 子句的某些保护。我强烈建议您理所当然地使用参数化查询:
这意味着您不必转义用户数据 他们将数据与代码分开 如果您从 Jet/ACE 迁移(无论是迁移此特定代码,还是只是您个人开始使用不同的数据库),您就不必担心了 对于日期等其他数据类型,您无需做任何工作即可将数据转换为适合数据库的形式(您也不需要对ToString
的所有调用。我不仅希望名为Text
的属性已经是一个字符串,而且您正在使用的事实字符串连接意味着无论如何字符串转换都会自动发生。)
【讨论】:
@Howard:没有比这更多的细节了吗?哦,好吧 - 这仍然比不知道那么多要好。当您的 SQL 被参数化时,可能会更容易发现问题 - 或者如果错误是由于您的数据包含引号引起的,它可能会消失。 哦,伟大的 SO 专家,请简要介绍一下使用 Jet/ACE 数据存储进行 SQL 注入的危险程度。您可能想在回复之前搜索 SO... @David-W-Fenton:在我看来,一些类的 SQL 注入攻击在这里不适用(那些涉及 DML),但其他类可能是(那些有直接"WHERE X='"+input+'"
代码的人。(我已经阅读了你在pcreview.co.uk/forums/thread-4021211.php 的帖子,其中提到了这一点,以及相关的 SO 帖子)。此外,参数化 SQL 将数据与代码分开,我认为这更干净。最后,我可以轻松看到有人将此代码从 Jet/ACE 移植到另一个数据库平台,而无需重新考虑所有可能的危险。
另外忘了提这意味着你不需要担心“清理”或转义输入。我认为参数化查询是处理 O'Reilly 姓氏的最佳方式。我敢说有特定于 Jet/ACE 的例程来执行转义 - 但是那些使用可以在数据库之间广泛移植的技术的好处是什么? (您可能需要在命名参数和附加参数之间进行更改,但基本方法是相同的。)
@Saeid:这似乎根本不相关。【参考方案2】:
我将此作为对重复问题的评论发布在:Syntax error in INSERT INTO statement in c# OleDb Exception cant spot the error
在表名周围加上括号 [] “用户”。它是 SQL 中的保留字 服务器。
“用户”也是 Access 中的保留字(由您的连接字符串中的提供者判断)。
但我完全同意 Jon 的观点——如果你修复了当前的实现,你只是打开了一个很大的安全漏洞(针对你的 User 表,同样如此!)
【讨论】:
【参考方案3】:如果您的数据库表包含使用 Microsoft Jet 4.0 保留字的列名,则可能会出现此问题。
更改数据库表中的列名,以免使用 Jet 4.0 保留字。
【讨论】:
我必须在查询中的表名和列名周围加上 [] 才能接受保留字。【参考方案4】:如果TargetWeight
、Height
和TargetCalories
是浮点或整数值,则它们不需要在SQL 语句中用引号引起来。
另外,与您的问题没有直接关系,但您应该真正考虑使用参数化查询。您的代码很容易受到 SQL 注入的攻击。
【讨论】:
【参考方案5】:public decimal codes(string subs)
decimal a = 0;
con_4code();
query = "select SUBJINTN.[SCODE] from SUBJINTN where SUBJINTN.[ABBR] = '" + subs.ToString() + "'";
cmd1 = new OleDbCommand(query, concode);
OleDbDataReader dr = cmd1.ExecuteReader();
这是 dr 中的错误,它说 DBMS 中的语法错误 ehile 运行良好
if (dr.Read())
a = dr.GetDecimal(0);
MessageBox.Show(a.ToString());
return a;
【讨论】:
OleDbDataReader dr = cmd1.ExecuteReader();在这一点上,它显示它的语法错误,而简单的 quary 工作良好............【参考方案6】:之后
cmd.CommandText="INSERT INTO User ([UserID], [Forename], [Surname], [DateOfBirth], [TargetWeight], [TargetCalories], [Height]) Values ('" + userid.Text.ToString() + "' , '" + fname.Text.ToString() + "' , '" + sname.Text.ToString() + "' , '" + dob.Text.ToString() + "' , '" + tarweight.Text.ToString() + "' , '" + tarcal.Text.ToString() + "' , '" + height.Text.ToString() + "')";
检查其中包含的内容,可能[DateOfBirth]
的格式不合法
【讨论】:
以上是关于使用此 INSERT INTO 语句和 .NET OleDb 命名空间时如何解决语法错误?的主要内容,如果未能解决你的问题,请参考以下文章
INSERT INTO 语句 c#.net Winforms Devexpress 中的语法错误?
MS Access 的 SQL INSERT INTO 语句
此查询在 Access 2010 中完美运行,但是当我尝试在代码中执行它时,在 INSERT INTO 语句中出现语法错误