数据库Command对象的参数顺序真的很重要吗?

我正在调试数据库操作代码,我发现虽然代码从未失败,但从未发生过正确的UPDATE。 这是代码:

condb.Open(); OleDbCommand dbcom = new OleDbCommand("UPDATE Word SET word=?,sentence=?,mp3=? WHERE id=? AND exercise_id=?", condb); dbcom.Parameters.AddWithValue("id", wd.ID); dbcom.Parameters.AddWithValue("exercise_id", wd.ExID); dbcom.Parameters.AddWithValue("word", wd.Name); dbcom.Parameters.AddWithValue("sentence", wd.Sentence); dbcom.Parameters.AddWithValue("mp3", wd.Mp3); 

但经过一些调整后,这有效:

  condb.Open(); OleDbCommand dbcom = new OleDbCommand("UPDATE Word SET word=?,sentence=?,mp3=? WHERE id=? AND exercise_id=?", condb); dbcom.Parameters.AddWithValue("word", wd.Name); dbcom.Parameters.AddWithValue("sentence", wd.Sentence); dbcom.Parameters.AddWithValue("mp3", wd.Mp3); dbcom.Parameters.AddWithValue("id", wd.ID); dbcom.Parameters.AddWithValue("exercise_id", wd.ExID); 
  1. 为什么在OleDb连接的情况下必须在WHERE子句中给出最后一个参数是如此重要? 之前使用过MySQL,我可以(并且通常会)首先编写WHERE子句的参数,因为这对我来说更合乎逻辑。

  2. 一般查询数据库时参数顺序是否重要? 一些性能问题还是什么?

  3. 是否有其他数据库(如DB2,Sqlite等)需要维护的特定顺序?

更新:我摆脱了? 并包括有和没有@专有名称。 订单非常重要。 在这两种情况下,只有在最后提到WHERE子句参数时才会发生实际更新。 更糟糕的是,在复杂的查询中,很难知道自己哪个订单是Access期望的,并且在订单发生变化的所有情况下,查询都没有完成预期的任务而没有警告/错误!

在Access中, ADODB.Command对象忽略参数名称。 实际上我可以使用伪名称(在SQL语句中甚至不存在)引用参数,而ADO并不关心。 似乎所关心的是,您提供的参数值的顺序与SQL语句中出现的参数的顺序完全相同 。 顺便说一下,如果我用SQL构建SQL语句,那也会发生什么? 占位符而不是命名参数。

虽然我意识到你的问题是关于c#和OleDbCommand ,但在我看来,像Dot.Net的OleDbCommand可能与Access的’ ADODB.Command 。 不幸的是,我不知道Dot.Net ……但那是我的预感。 🙂

订单很重要因为使用? 占位符在命令字符串中。

如果要按任何顺序列出参数,最好使用命名参数,例如@word,@ sentence等。

 condb.Open(); OleDbCommand dbcom = new OleDbCommand("UPDATE Word SET word=@word,sentence=@sentence,mp3=@mp3 WHERE id=@id AND exercise_id=@exercise_id", condb); dbcom.Parameters.AddWithValue("@id", wd.ID); dbcom.Parameters.AddWithValue("@exercise_id", wd.ExID); dbcom.Parameters.AddWithValue("@word", wd.Name); dbcom.Parameters.AddWithValue("@sentence", wd.Sentence); dbcom.Parameters.AddWithValue("@mp3", wd.Mp3); 

我一直在使用OleDbCommand及其针对Access DB的参数集合进行一些测试。 参数的排序当然是必要的,因为这是OLE DB .NET提供程序的限制 。 但是在使用问号作为占位符时可能会遇到一个问题。

假设您的Access数据库中有一个查询(“存储过程”),看起来像这样,在这里非常简化:

 parameters prmFirstNumber Long, prmSecondNumber Long; select fullName from tblPersons where numberOfCars < prmFirstNumber And numberOfPets < prmSecondNumber And numberOfBooks beteween prmFirstNumber And prmSecondNumber 

在这里,您会看到只需更改为问号就会破坏查询。

我发现,作为解决方案,您实际上可以使用参数名称。 因此,您可以让上面的查询保持原样。 您只需在运行查询时使用相同的顺序。 就像在这种情况下,首先添加参数prmFirstNumber然后添加prmSecondNumber,然后运行查询。

当重用参数时,即多次执行查询并每次为参数设置新值时,必须在定义参数后立即调用命令对象的prepare方法。 还有一些细节需要完成,请查看“准备”文档。 不调用prepare会导致奇怪的行为而不会出现错误消息,这些消息可能会破坏您的数据库或导致向用户显示错误的信息。

我还可以补充一点,当查询存储在Access DB中并且指定了参数时,就像我上面的例子一样,参数的排序由参数-section明确定义。

我还制作了一个例程“retrieveDeclaredJetParametersInOrder”,它以正确的顺序自动用这些命名参数填充OleDbCommand对象。 所以我的代码看起来像这样:

 Dim cmd As New OleDbCommand("qryInAccessDB", Conn) cmd.CommandType = CommandType.StoredProcedure Conn.Open() retrieveDeclaredJetParametersInOrder(cmd) cmd.Parameters("prmOneOfTheParametersPerhapsTheLastOneDeclared").Value = 1 cmd.Parameters("prmAnotherone").Value = 20 cmd.Parameters("prmYetAnotherPerhapsTheFirstOneDeclared").Value = 300 cmd.ExecuteNonQuery() Conn.Close() 

所以,正如你所看到的,我可以处理它,就好像参数被命名一样,并且永远不必为他们的排序烦恼。

retrieveDeclaredJetParametersInOrder当然会增加额外的执行时间,因为它涉及对DB的额外调用,它会检索SQL文本,然后解析出参数名称和类型。