![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с ADO. Выделение параметров.
И. Павел © (2010-06-24 09:10:00)Здравствуйте.
Пост получился длинным, так что основной вопрос я выделил жирным, на всякий случай :) Все остальное – просто дополнение к этому.
Я решил разобраться в том, как правильно работать с ADO. В частности, перешел на ADODataSet + ADOCommand вместо использования везде ADOQuery. Решил максимально применять параметры, чтобы избежать ряда трудностей. Ища в сети информацию про ADO, я натолкнулся на следующее:
1.
В сети встречаются темы, в которых обсуждают недостатки автоматического распознавания параметров: оно не дружит с табуляцией, иногда может воспринять за параметр не то двоеточие. А вот эта ошибка свидетельствует о нестабильной работе распознавания параметров:
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=62550
Да и вообще, какой смысл тратить время на то, чтобы парсировать запрос автоматически (для каждого запроса к SQL SERVER соединенние с сервером происходит дважды: при задании запроса и при его выполнении)? Вручную это делать удобнее и, похоже, надежнее. Насколько я понял, для этого нужно писать вместо параметров символ “?”. Но, т.к.OLE DB не поддерживает имена параметров, то важен порядок. Подскажите, пожалуйста, верно ли, что при работе через ADO с запросом любой сложности и уровнем вложенности к любой базе (MS SQL SERVER, Access и т.д.), проще говоря, всегда, AddParameter для создания параметров нужно вызывать в том же порядке, в каком идут знаки “?” слева-направо в CommandText?
Я написал модуль данных для работы с параметрами вручную (ParamCheck = false). Буду рад, если кто-нибудь согласиться его проверить.
2.
Вот еще это нашел в сети:
- “Использовать параметры правильным образом я боюсь после того, как дельфа стала съедать время от времени часть их длины. Именно поэтому я использую Query, а не StoredProc.” http://www.delphimaster.ru/cgi-bin/forum.pl?id=1263807978&n=1
- “это нормально, что параметрический запрос отбрасывает хвост?” http://www.cyberforum.ru/delphi-beginners/thread112147.html
Ну это уже, ИМХО, очень сомнительные утверждения. Думаю, что это просто ошибки программистов, в которых они обвинили Delphi и ADO. Но все же хотелось бы знать: может действительно встречается что-то подобное? Хотя, думаю, если встречалось бы, про это бы говорили очень часто и в конце концов, исправили бы.
И. Павел (2010-06-25 13:27:00) [1]Anatoly Podgoretsky ©
Спасибо.
Anatoly Podgoretsky (2010-06-25 12:58:00) [2]> И. Павел (25.06.2010 10:20:13) [13]
> У меня MS SQL принимает цепочку инструкций из CommandText и выполняет.
Но зараз только одну, затем другую
И. Павел (2010-06-25 11:07:00) [3]> [14] sniknik © (25.06.10 10:43)
Ясно, спасибо.
sniknik (2010-06-25 10:43:00) [4]> Про недостатки BeginTrans/CommitTrans/RollBackTrans я не знал (похоже, у ADO полно странных сюрпризов...)
не недостатки... блин.
просто, что думаешь будет при подключении к движку транзакций не поддерживающего? ничего не будет, а ты будешь уверен что у тебя все в ажуре.
ADO посредник, реальные действия выполняет движок/sql сервер. вот его ты и должен изучать.
И. Павел (2010-06-25 10:20:00) [5]sniknik ©
Спасибо. Попробую использовать явные транзакции (это ведь BEGIN TRANSACTION/COMMIT/ROLLBACK?). Про недостатки BeginTrans/CommitTrans/RollBackTrans я не знал (похоже, у ADO полно странных сюрпризов...)
Насчет табуляций и двоеточий я имел в виду только в самом запросе. В значениях без них, конечно, не обойтись. До использования двоеточий в запросах я пока не добрался.
> и что тут не ясного?
Просто формулировку в справке можно понять так, что CommandText всегда должен содержать только одну инструкцию: "The TADOCommand component executes the command specified in its CommandText property. One command may be executed at a time." Вот я и хочу уточнить - так ли это. У меня MS SQL принимает цепочку инструкций из CommandText и выполняет.
Пункт 5 я просто не так сформулировал. Я имел ввиду, что, учитывая справку по ADOCommand, видимо лучше писать:
CommandText := 'insert ...';
Execute;
CommandText := 'insert ...';
Execute;
...
чем:
CommandText := 'insert ... ; insert ... ; ...';
Execute;
Так ли это?
sniknik (2010-06-25 09:38:00) [6]> 2. Абсолютно все значения передаются через параметры
абсолютного ничего не бывает, все должно быть к месту... не случится ничего страшного если какое-то целочисленное (однозначное) значение в разово выполняемом запросе вставить прямо в него. вот если цикл из одного запроса то да, лучше сформировать один со всеми параметрами и после его выполнять меняя только их.
главное понимание, а не абсолюты.
> 3. Табуляции и двоеточия, по возможности, не используются вообще
с чего бы? в данных параметров они ни на что не влияют, а в составе запроса... если уж нужны то никуда от этого не деться.
какие то странные у тебя выводы.
> 5. Если нужно выполнить транзакцию из нескольких инструкций
транзакции не для того чтобы выполнять/завертывать в них несколько инструкций... они для того обеспечения целостности, если например нужно сохранить такие блок данных/запись в разные таблицы, что одна часть без другой ничего не значит/приведет к ошибкам.
а в твоем случае это просто злоупотребление транзакциями, совершенно бессмысленное. тем более использование локальной транзакции (не всегда работает через движок), лучше писать явно (имхо. т.к. если понимаешь и знаешь что вот в этом случае она отработает именно так как ожидаешь то тоже ничего страшного в использовании этого метода. но чисто ради формирования правильных привычек...).
> "One command may be executed at a time."
и что тут не ясного? движок может выполнять параллельные команды, а вот команда пока не отработает до конца не могут выполняться в то же время.
И. Павел (2010-06-25 08:47:00) [7]Итак, учитывая все мне уже известное про ADO, я написал примерный способ работы с ним, чтобы избежать подводных камней. Проверьте его, пожалуйста, и если нужно – дополните или укажите на ошибки.
1. Работа осуществляется через ADOCommand и ADODataSet, связанные с одним общим TADOConnection (за исключением случаев, когда нужно работать в нескольких потоках - тогда на каждый поток по своему ADOConnection).
2. Абсолютно все значения передаются через параметры
3. Табуляции и двоеточия, по возможности, не используются вообще
4. В CommandText за раз пишется по одной целой инструкции.
5. Если нужно выполнить транзакцию из нескольких инструкций (например несколько insert-ов) то делается BeginTrans, потом в CommandText пишется первая инструкция, делается Execute, потом, то же самое для второй, и т.д. до CommitTrans.
PS: В справке для TADOCommand нашел фразу: "One command may be executed at a time." А в русском варианте ( http://www.znannya.org/?view=concept:124) ее перевели: "Способен за один раз исполнять одну и только одну команду". Подскажите, пожалуйста, это действительно важно, и если да, почему?
И. Павел (2010-06-24 15:58:00) [8]Кажется разобрался - все прекрасно работает. При парсировании второго запроса от базы даже приходит информация с типом только что созданного поля "pole", так что эта запись, наверное, даже более предпочтительна.
sniknik ©, Amoeba_еще раз большое спасибо.
И. Павел (2010-06-24 15:00:00) [9]Подскажите, пожалуйста, под необходимостью вносить запрос целиком в ADO подразумевается ведь просто не делить на части одну инструкцию? Можно ведь отделять инструкции друг от друга в пределах одной транзакции, даже если они зависимы друг от друга и вторая, например, обрабатывает данные, сгенерированные первой, а не городить все в одном CommandText?
Например:
DMQ.ADOCon.BeginTrans;
try
ADOC.CommandText := 'CREATE TABLE tab1 (pole integer);';
ADOC.Execute;
ADOC.CommandText := 'INSERT INTO tab1 (pole) VALUES (:TPole)';
ADOC.Parameters.ParseSQL(ADOC.CommandText, true);
with ADOC.Parameters.ParamByName('TPole') do
begin
DataType := ftInteger;
Direction := pdInput;
Value := 100;
end;
ADOC.Execute;
//...
//Прочие действия по обработке тех же и других данных
//...
DMQ.ADOCon.CommitTrans;
except
DMQ.ADOCon.RollbackTrans;
Application.MessageBox('Транзакция отменена', 'Ошибка', 0);
end;
Anatoly Podgoretsky (2010-06-24 14:41:00) [10]> И. Павел (24.06.2010 09:54:03) [3]
Нет и поэтому нет кучи проблем с этим ADD
12 (2010-06-24 12:57:00) [11]> что использовать Query.Add не желательно
моя просто из лени перестал использовать
прежде чем сделать add, надо делать clear
а *.text := 'erwe'
делает сразу.
И. Павел (2010-06-24 12:28:00) [12]sniknik ©, Amoeba_спасибо.
Amoeba_ (2010-06-24 11:45:00) [13]
> И. Павел © (24.06.10 09:10)
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=733
sniknik (2010-06-24 11:32:00) [14]плохого ничего нет. но мешать он иногда может, например если символ ":" часть запроса. случай довольно редкий (не в данных, т.к. их значения в параметрах и не влияют, а именно запроса) но не невозможный (есть вызовы типа "SELECT * FROM ::fn_helpcollations()", или "... FROM 'LDAP:\\xxxx'"). вот тут авто определение приходится отключать... ну а если в таком запросе нужны параметры то и делать их самому описывая в запросе вопросом, как ты хотел вначале.
И. Павел (2010-06-24 09:54:00) [15]Большое вам спасибо, sniknik ©.
Я, кстати, где-то находил информацию о том, что использовать Query.Add не желательно, но не смог соединить одно с другим :).
Тогда, раз ничего плохого в использовании автоматического парсирования нет, буду продолжать использовать его.
Вот и еще один плюс ADODataSet и AODCommand – там нет “Add”.
sniknik (2010-06-24 09:38:00) [16]> А вот эта ошибка свидетельствует о нестабильной работе распознавания параметров:
эта ошибка свидетельствует о глупости тех кто ее получает, не более... да еще и выводы.
а на самом деле в адо попросту НЕТ (а значит и не должно) возможности вносить запрос частями, только цельным, и сделано это частично и из-за того, что запрос подвергается обработке.
возьми например аналог, обрежь часть процедуры снизу, наполовину(/две трети как в ссылке) и попробуй скомпилить. получилось? ах какой дельфи глючный оказывается...
> Думаю, что это просто ошибки программистов, в которых они обвинили Delphi и ADO.
и не сомневайся. большинство ламеров так и делают. нормальные ищут ошибки там в последнюю очередь, когда и свой код уже перепроверен, и есть уверенность в том что изучил и понимаешь процесс.
И. Павел (2010-06-24 09:14:00) [17]Я забыл указать путь к своему модулю: http://paste.org.ru/?w664j6
Пример работы с ним: http://paste.org.ru/?9wacbb