Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.09.19;
Скачать: CL | DM;

Вниз

Работа с ADO. Выделение параметров.   Найти похожие ветки 

 
И. Павел ©   (2010-06-24 09:10) [0]

Здравствуйте.

Пост получился длинным, так что основной вопрос я выделил жирным, на всякий случай :) Все остальное – просто дополнение к этому.

Я решил разобраться в том, как правильно работать с 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://delphimaster.net/view/3-1263807978/
- “это нормально, что параметрический запрос отбрасывает хвост?” http://www.cyberforum.ru/delphi-beginners/thread112147.html

Ну это уже, ИМХО, очень сомнительные утверждения. Думаю, что это просто ошибки программистов, в которых они обвинили Delphi и ADO. Но все же хотелось бы знать: может действительно встречается что-то подобное? Хотя, думаю, если встречалось бы, про это бы говорили очень часто и в конце концов, исправили бы.


 
И. Павел ©   (2010-06-24 09:14) [1]

Я забыл указать путь к своему модулю: http://paste.org.ru/?w664j6
Пример работы с ним: http://paste.org.ru/?9wacbb


 
sniknik ©   (2010-06-24 09:38) [2]

> А вот эта ошибка свидетельствует о нестабильной работе распознавания параметров:
эта ошибка свидетельствует о глупости тех кто ее получает, не более... да еще и выводы.

а на самом деле в адо попросту НЕТ (а значит и не должно) возможности вносить запрос частями, только цельным, и сделано это частично и из-за того, что запрос подвергается обработке.
возьми например аналог, обрежь часть процедуры снизу, наполовину(/две трети как в ссылке) и попробуй скомпилить. получилось? ах какой дельфи глючный оказывается...

> Думаю, что это просто ошибки программистов, в которых они обвинили Delphi и ADO.
и не сомневайся. большинство ламеров так и делают. нормальные ищут ошибки там в последнюю очередь, когда и свой код уже перепроверен, и есть уверенность в том что изучил и понимаешь процесс.


 
И. Павел ©   (2010-06-24 09:54) [3]

Большое вам спасибо, sniknik ©.
Я, кстати, где-то находил информацию о том, что использовать Query.Add не желательно, но не смог соединить одно с другим :).
Тогда, раз ничего плохого в использовании автоматического парсирования нет, буду продолжать использовать его.
Вот и еще один плюс ADODataSet и AODCommand – там нет “Add”.


 
sniknik ©   (2010-06-24 11:32) [4]

плохого ничего нет. но мешать он иногда может, например если символ ":" часть запроса. случай довольно редкий (не в данных, т.к. их значения в параметрах и не влияют, а именно запроса)  но не невозможный (есть вызовы типа "SELECT * FROM ::fn_helpcollations()", или  "... FROM "LDAP:\\xxxx""). вот тут авто определение приходится отключать... ну а если в таком запросе нужны параметры то и делать их самому описывая в запросе вопросом, как ты хотел вначале.


 
Amoeba_   (2010-06-24 11:45) [5]


> И. Павел ©   (24.06.10 09:10)  

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=733


 
И. Павел ©   (2010-06-24 12:28) [6]

sniknik ©, Amoeba_ спасибо.


 
12 ©   (2010-06-24 12:57) [7]

> что использовать Query.Add не желательно

моя просто из лени перестал использовать
прежде чем сделать add, надо делать clear
а *.text := "erwe"
делает сразу.


 
Anatoly Podgoretsky ©   (2010-06-24 14:41) [8]

> И. Павел  (24.06.2010 09:54:03)  [3]

Нет и поэтому нет кучи проблем с этим ADD


 
И. Павел ©   (2010-06-24 15: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;


 
И. Павел ©   (2010-06-24 15:58) [10]

Кажется разобрался - все прекрасно работает. При парсировании второго запроса от базы даже приходит информация с типом только что созданного поля "pole", так что эта запись, наверное, даже более предпочтительна.

sniknik ©, Amoeba_ еще раз большое спасибо.


 
И. Павел ©   (2010-06-25 08:47) [11]

Итак, учитывая все мне уже известное про 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) ее перевели: "Способен за один раз исполнять одну и только одну команду". Подскажите, пожалуйста, это действительно важно, и если да, почему?


 
sniknik ©   (2010-06-25 09:38) [12]

> 2. Абсолютно все значения передаются через параметры
абсолютного ничего не бывает, все должно быть к месту... не случится ничего страшного если какое-то целочисленное (однозначное) значение в разово выполняемом запросе вставить прямо в него. вот если цикл из одного запроса то да, лучше сформировать один со всеми параметрами и после его выполнять меняя только их.
главное понимание, а не абсолюты.

> 3. Табуляции и двоеточия, по возможности, не используются вообще
с чего бы? в данных параметров они ни на что не влияют, а в составе запроса... если уж нужны то никуда от этого не деться.
какие то странные у тебя выводы.

> 5. Если нужно выполнить транзакцию из нескольких инструкций
транзакции не для того чтобы выполнять/завертывать в них несколько инструкций...  они для того обеспечения целостности, если например нужно сохранить такие блок данных/запись в разные таблицы, что одна часть без другой ничего не значит/приведет к ошибкам.
а в твоем случае это просто злоупотребление транзакциями, совершенно бессмысленное. тем более использование локальной транзакции (не всегда работает через движок), лучше писать явно (имхо. т.к. если понимаешь и знаешь что вот в этом случае она отработает именно так как ожидаешь то тоже ничего страшного в использовании этого метода. но чисто ради формирования правильных привычек...).

> "One command may be executed at a time."
и что тут не ясного? движок может выполнять параллельные команды, а вот команда пока не отработает до конца не могут выполняться в то же время.


 
И. Павел ©   (2010-06-25 10:20) [13]

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 10:43) [14]

> Про недостатки BeginTrans/CommitTrans/RollBackTrans я не знал (похоже, у ADO полно странных сюрпризов...)
не недостатки... блин.
просто, что думаешь будет при подключении к движку транзакций не поддерживающего? ничего не будет, а ты будешь уверен что у тебя все в ажуре.

ADO посредник, реальные действия выполняет движок/sql сервер. вот его ты и должен изучать.


 
И. Павел ©   (2010-06-25 11:07) [15]

> [14] sniknik ©   (25.06.10 10:43)

Ясно, спасибо.


 
Anatoly Podgoretsky ©   (2010-06-25 12:58) [16]

> И. Павел  (25.06.2010 10:20:13)  [13]

> У меня MS SQL принимает цепочку инструкций из CommandText и выполняет.

Но зараз только одну, затем другую


 
И. Павел ©   (2010-06-25 13:27) [17]

Anatoly Podgoretsky ©
Спасибо.



Страницы: 1 вся ветка

Текущий архив: 2010.09.19;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.012 c
2-1277224941
Сергей
2010-06-22 20:42
2010.09.19
Пропуск строки при сохранении в ini


15-1277226885
Who_is_you?
2010-06-22 21:14
2010.09.19
Как добавить новый компонент


2-1277196510
Who_is_you?
2010-06-22 12:48
2010.09.19
сбои в асинхронном приеме с сом порта


15-1276971762
sniknik
2010-06-19 22:22
2010.09.19
Перехват ссылки в TWebBrowser.


2-1277215414
SIV500
2010-06-22 18:03
2010.09.19
Отослать сообщение окну...