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

c# database ms-access oledbcommand dbcommand

3291 观看

3回复

46461 作者的声誉

我正在调试数据库操作代码,但我发现尽管代码从未如此失败,但从未发生过正确的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期望的顺序是什么,在所有更改顺序的情况下,查询都不会在没有警告/错误的情况下履行其预期的职责!

作者: nawfal 的来源 发布者: 2011 年 8 月 23 日

回应 (3)


2

2682 作者的声誉

该命令很重要,因为使用了?命令字符串中的占位符。

如果要以任何顺序列出参数,则最好使用命名参数,例如@ 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);                         
作者: Roy Goode 发布者: 23.08.2011 06:24

5

88446 作者的声誉

决定

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

虽然我意识到您的问题与c#有关OleDbCommand,但在我看来Dot.Net的OleDbCommand运行方式可能与Access'相同ADODB.Command。不幸的是,我不了解Dot.Net ...但这是我的直觉。:-)

作者: HansUp 发布者: 11.07.2012 01:48

2

639 作者的声誉

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

假设您的Access DB中有一个查询(“存储过程”)如下所示,在此非常简化:

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中时,如上面的示例所示,则参数的顺序由parameters-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的额外调用,在DB中检索SQL文本,然后解析出参数名称和类型。

作者: Magnus 发布者: 24.11.2012 05:02
32x32