Действительно ли важен порядок параметров для командного объекта базы данных? - PullRequest
4 голосов
/ 23 августа 2011

Я отлаживал код операции с базой данных и обнаружил, что правильного ОБНОВЛЕНИЯ никогда не было, хотя код никогда не давал сбои как таковой. Это код:

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

  2. Важен ли порядок параметров при запросах к базе данных в целом? Некоторые проблемы с производительностью или что-то в этом роде?

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

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

Ответы [ 3 ]

5 голосов
/ 11 июля 2012

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

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

2 голосов
/ 24 ноября 2012

Я проводил некоторые тесты с использованием OleDbCommand и его сбора параметров для базы данных Access.Упорядочение параметров, конечно, необходимо, поскольку это ограничение поставщика 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 с указанными параметрами, как в моемВ приведенном выше примере порядок параметров однозначно определяется разделом параметров.

Я также создал подпрограмму «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()

Итак, как вы видите, я могу обрабатывать его так, как если бы параметры были названы, и мне никогда не придется беспокоиться об их упорядочении.

The retrieveDeclaredJetParametersInOrderконечно, добавляет дополнительное время к выполнению, так как это включает дополнительный вызов БД, где он получает SQL-текст, а затем анализирует имена и типы параметров.

2 голосов
/ 23 августа 2011

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

Если вы хотите перечислить параметры в любом порядке, лучше использовать именованные параметры, такие как @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);                         
...