Является ли порядок параметров для объекта Command 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);
  • Почему так важно, чтобы параметрам в предложении WHERE было дано последнее в случае соединения OleDb? Работая с MySQL ранее, я мог (и обычно делать) сначала записывать параметры предложения WHERE, потому что это более логично для меня.

  • Является ли порядок параметров важным при запросе базы данных в целом? Некоторые проблемы производительности или что-то еще?

  • Существует ли конкретный порядок поддержки в случае других баз данных, таких как DB2, Sqlite и т.д.

Обновление: Я избавился от ? и включил собственные имена с и без @. Порядок действительно важен. В обоих случаях только когда упоминались параметры предложения WHERE, произошло фактическое обновление. Чтобы усугубить материю, в сложных запросах, трудно понять, какой заказ является ожиданием доступа, и во всех ситуациях, когда порядок изменен, запрос не выполняет свою предполагаемую работу без предупреждения/ошибки.

Ответ 1

Внутри Access объект ADODB.Command игнорирует имена параметров. Фактически я могу ссылаться на параметр, используя фиктивное имя (которое даже не существует в SQL-заявлении), и ADO не волнует. Все, что, по-видимому, заботится о том, что вы предоставляете значения параметров в том же порядке, что и те параметры, которые содержатся в инструкции SQL. BTW, это также происходит, если я создаю инструкцию SQL с ? place-holder вместо названных параметров.

Пока я понимаю, что ваш вопрос о С# и OleDbCommand, мне кажется, что Dot.Net OleDbCommand может работать так же, как Access 'ADODB.Command. К сожалению, я не знаю Dot.Net... но это моя догадка.: -)

Ответ 2

Порядок важен из-за использования? заполнители в командной строке.

Если вы хотите перечислить параметры в любом порядке, лучше использовать именованные параметры, такие как @word, @sentence и т.д.

condb.Open();
OleDbCommand dbcom = new OleDbCommand("UPDATE Word SET [email protected],[email protected],[email protected] WHERE [email protected] AND [email protected]_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);                         

Ответ 3

Я делал некоторые тесты с использованием OleDbCommand и его набора параметров с помощью Access DB. Разумеется, необходимо упорядочить параметры, поскольку это ограничение поставщика OLE DB.NET. Но есть проблема, с которой вы можете столкнуться при использовании вопросительных знаков в качестве держателей мест.

Скажите, что у вас есть запрос ( "хранимая процедура" ) в вашей БД доступа, который выглядит так: здесь очень упрощается:

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

Здесь вы видите, что простое изменение вопросительных знаков приведет к поломке запроса.

Я нашел, как решение этого, что вы действительно можете использовать имена для параметров. Таким образом, вы можете оставить запрос выше, как есть. Вам просто нужно использовать тот же порядок при запуске запроса. Как и в этом случае, вы сначала добавляете параметр prmFirstNumber, а затем prmSecondNumber, а затем запускаете запрос.

При повторном использовании параметров, т.е. выполнении запроса более одного раза и каждый раз задавая новые значения для параметров, нужно сразу вызвать метод подготовки объекта команды сразу после определения параметров. Здесь есть некоторые детали, которые необходимо выполнить, посмотрите документацию для "подготовки". Не вызывать сборку вызывает странное поведение без сообщений об ошибках, которые могут повредить вашу базу данных или вызвать неверную информацию для пользователей.

Я могу добавить также, что когда запросы хранятся в БД доступа с указанными параметрами, как в моем примере выше, тогда порядок параметров однозначно определяется секцией параметров.

Я также сделал процедуру "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, конечно, добавляет дополнительное время на выполнение, поскольку оно включает дополнительный вызов в БД, где он извлекает текст SQL, а затем анализирует имена и типы параметров.