Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работа с 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


Наверх

Титульная страница Поиск, карта сайта Написать письмо