Запросы с параметрами
Запросы с параметрами
исторически получилось, что вместо параметров в запросах я всегда писал полный текст с помощью Format
т.е. вместо:
Query.SQL.Text:='SELECT * FROM SomeTable WHERE id=:id';
Query.ParamByName('id').Value:=id;
писал:
Query.SQL.Text:=Format('SELECT * FROM SomeTable WHERE id=%d', [id]);
причина такого использования была в том, что параметры при отладке и Query.SQL.SaveToFile('file.sql'); сохраняли не текущие значения, что часто неудобно, да и возникали проблемы с некоторыми типами полей при использовании параметров (сейчас уже не помню какие, но кажется большая часть - с датами).
вопрос: что дает использование параметров, кроме удобства при чтении кода (и то при сильно мнемонических названиях)? и какое ограничение может быть при использовании Format()?
т.е. вместо:
Query.SQL.Text:='SELECT * FROM SomeTable WHERE id=:id';
Query.ParamByName('id').Value:=id;
писал:
Query.SQL.Text:=Format('SELECT * FROM SomeTable WHERE id=%d', [id]);
причина такого использования была в том, что параметры при отладке и Query.SQL.SaveToFile('file.sql'); сохраняли не текущие значения, что часто неудобно, да и возникали проблемы с некоторыми типами полей при использовании параметров (сейчас уже не помню какие, но кажется большая часть - с датами).
вопрос: что дает использование параметров, кроме удобства при чтении кода (и то при сильно мнемонических названиях)? и какое ограничение может быть при использовании Format()?
Вкратце:
1. Запрос, перед исполнением, сначала надо скомпилировать. Для этого компонента доступа отправляет его текст на сервер (по команде Prepare), и получает от него в скомпилированном виде (BLR), вместе с планом выполнения.
2. Скомпилировав его раз (с параметром), запрос можно выполнять неограниченное число раз, меняя только значения параметров. Использование явных значений требует перекомпилирования при каждом выполнении (если "параметры" не изменились), увеличивая сетевой трафик и время отклика приложения.
1. Запрос, перед исполнением, сначала надо скомпилировать. Для этого компонента доступа отправляет его текст на сервер (по команде Prepare), и получает от него в скомпилированном виде (BLR), вместе с планом выполнения.
2. Скомпилировав его раз (с параметром), запрос можно выполнять неограниченное число раз, меняя только значения параметров. Использование явных значений требует перекомпилирования при каждом выполнении (если "параметры" не изменились), увеличивая сетевой трафик и время отклика приложения.
Re: Запросы с параметрами
Программирование - это большое, большое поле, на котором каждый при большом желании может топтать свою тропу. Но твоя тропинка, на этом сайте, как мне кажется, будет оценена как проктология.
Не думаю, что на твой вопрос кто - либо будет отвечать детально. Смотри литературу и изучай матчасть.
Насколько можно судить по запросам с датами чаще всего проблемы возникают, когда в запрос вместо параметра DateTime пытаются засунуть строку.
Не думаю, что на твой вопрос кто - либо будет отвечать детально. Смотри литературу и изучай матчасть.
Насколько можно судить по запросам с датами чаще всего проблемы возникают, когда в запрос вместо параметра DateTime пытаются засунуть строку.
Re: Запросы с параметрами
мсье ходил такими путями?SAMZ писал(а):Программирование - это большое, большое поле, на котором каждый при большом желании может топтать свою тропу. Но твоя тропинка, на этом сайте, как мне кажется, будет оценена как проктология.
собственно, мне кажется специализированный форум для того, чтобы уточнить непонятые моменты и ветка еще более специализированная, соответствует вопросу.SAMZ писал(а): Не думаю, что на твой вопрос кто - либо будет отвечать детально. Смотри литературу и изучай матчасть.
зачем отвечать, если нечего ответить по вопросу?
конечно, можно показать свою крутость знанием фраз "rtfm", "учи матчасть" и т.д.
я не говорил, что проблемы были только с датами.SAMZ писал(а):Насколько можно судить по запросам с датами чаще всего проблемы возникают, когда в запрос вместо параметра DateTime пытаются засунуть строку.
* как долго хранится скомпилированный результат?CyberMax писал(а):Вкратце:
1. Запрос, перед исполнением, сначала надо скомпилировать. Для этого компонента доступа отправляет его текст на сервер (по команде Prepare), и получает от него в скомпилированном виде (BLR), вместе с планом выполнения.
2. Скомпилировав его раз (с параметром), запрос можно выполнять неограниченное число раз, меняя только значения параметров. Использование явных значений требует перекомпилирования при каждом выполнении (если "параметры" не изменились), увеличивая сетевой трафик и время отклика приложения.
* если у меня очередь из 50 последовательных запросов, то будет ли повторная компиляция?
* если такой же запрос из другого коннекта, компиляция берется старая?
см. дальше.* как долго хранится скомпилированный результат?
какая очередь? Ты о чем?* если у меня очередь из 50 последовательных запросов, то будет ли повторная компиляция?
опять ерунда.* если такой же запрос из другого коннекта, компиляция берется старая?
все действует только в контексте вызовов Датасета (IBQuery, IBDataSet и т.п.) .Prepare и .Execute.
после Prepare можно выполнить Execute сколько угодно раз.
с датами, действительно, самая проктология, когда их в виде строки на сервер кидают, хоть в запросе, хоть через параметр. Передавать надо как DateTime.но кажется большая часть - с датами).
По-моему о программерской лени вроде
ParamByName('date').asString:=Edit1.Text
я уже где-то писал.
Код: Выделить всё
q.SQL.Text := 'SELECT * FROM TBL WHERE ID = :ID';
q.Prepare; // Тут первая и единственная процедура парсинга и компиляции запроса
while (i < 10000) do begin
q.ParamByName('ID').AsInteger := i;
q.ExecQuery;
// Тут что-то делаем с результатом запроса
i := i+1;
end;
А закрывать набор Пушкин будет?
Код: Выделить всё
q.SQL.Text := 'SELECT * FROM TBL WHERE ID = :ID';
q.Prepare; // Тут первая и единственная процедура парсинга и компиляции запроса
while (i < 10000) do begin
q.ParamByName('ID').AsInteger := i;
q.ExecQuery;
// Тут что-то делаем с результатом запроса
q.Close;
i := i+1;
end;
while i:=... dokdv писал(а):какая очередь? Ты о чем?* если у меня очередь из 50 последовательных запросов, то будет ли повторная компиляция?
begin
Query.SQL:='...';//1
Query.ExecSQL;
...
Query.SQL:='...';//2
Query.ExecSQL;
...
Query.SQL:='...';//49
Query.ExecSQL;
...
Query.SQL:='...';//50
Query.ExecSQL;
...
end;
т.е. в каждой итерации будет использоваться тот же результат по Prepare?
т.е. если я изменю запрос, то Prepare будет заново выполняться?kdv писал(а):опять ерунда.* если такой же запрос из другого коннекта, компиляция берется старая?
все действует только в контексте вызовов Датасета (IBQuery, IBDataSet и т.п.) .Prepare и .Execute.
после Prepare можно выполнить Execute сколько угодно раз.
и параметрический запрос имеет преимущество только, если я один и тот же запрос вызываю несколько раз?
результат Prepare хранится на сервере или в компоненте?
я много лет работал с MySQL, там практически все по-другому, поэтому и задаю вопросы на недопонятые мной моментыkdv писал(а):с датами, действительно, самая проктология, когда их в виде строки на сервер кидают, хоть в запросе, хоть через параметр. Передавать надо как DateTime.но кажется большая часть - с датами).
По-моему о программерской лени вроде
ParamByName('date').asString:=Edit1.Text
я уже где-то писал.
посмотри код компонент Prepare+Execute это пара методов для ОДНОГО текста запроса.т.е. в каждой итерации будет использоваться тот же результат по Prepare?
разумеется. Prepare "дает возможность" выполнять один и тот же запрос с разным набором параметров.т.е. если я изменю запрос, то Prepare будет заново выполняться?
агаи параметрический запрос имеет преимущество только, если я один и тот же запрос вызываю несколько раз?
разумеется на сервере. результат prepare это план запроса, структуры, и его код для исполнения сервером.результат Prepare хранится на сервере или в компоненте?
да уж прямо по другому. параметры везде одинаковы, а особенности форматов дат известны давно, например с самых первых Windows.я много лет работал с MySQL, там практически все по-другому,
хотя есть
FIBPlus
TpFIBDataSet
запрос что-то вроде:
SELECT MyTable.id, ... FROM MyTable LEFT JOIN ...
WHERE ...
AND MyTable.id NOT IN (:id_used)
ORDER BY MyTable.id;
дальше в коде пишу:
DataSet.ParamByName('id_used').Value := '123, 124, 125';
и на открытии запроса ошибка, потому, что в DataSet.ParamByName('id_used').Value попадает '123. 124. 125'
из-за чего такие подмены и как побороть не знаю
даже в IBExpert такая же фигня выходит
FIBPlus
TpFIBDataSet
запрос что-то вроде:
SELECT MyTable.id, ... FROM MyTable LEFT JOIN ...
WHERE ...
AND MyTable.id NOT IN (:id_used)
ORDER BY MyTable.id;
дальше в коде пишу:
DataSet.ParamByName('id_used').Value := '123, 124, 125';
и на открытии запроса ошибка, потому, что в DataSet.ParamByName('id_used').Value попадает '123. 124. 125'
из-за чего такие подмены и как побороть не знаю
даже в IBExpert такая же фигня выходит
мда. сила мысли... почему сервер должен соображать что ты в параметр передаешь не строку а некое перечисление неопознанного типа данных, да еще разделенного запятыми, а не точкой с запятой например, или пробелом?из-за чего такие подмены и как побороть не знаю
на первый раз предупреждение
а) за неоригинальность идеи
б) за нечтение FAQ: http://www.ibase.ru/ibfaq.htm#inparam