![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
SQL выражение в ADO вызывает исключение в msvcrt.dll
oxffff © (2007-11-19 09:59:00)Добрый день.
Кто нибудь встречался с такой ситуацией.
Имеется TADOQuery и следующий запрос
select value,
(select count(*) from SourceTrains B join SourceVagons C
on B.TrainID=C.TrainID
where convert(char(10),B.Traindate,2)=A.value
) as 'Total',
(select count(*) from SourceTrains B join SourceVagons C
on B.TrainID=C.TrainID
where convert(char(10),B.Traindate,2)=A.value and
convert(char(2),B.Traindate,8)>=0 and
convert(char(2),B.Traindate,8)<6
) as '0-6 Total',
..............
from (select convert(char(10),Traindate,2) as value
from SourceTrains group by convert(char(10),Traindate,2)
) A
where trainId=:param1
После того как делаем
AdoQuery.SQL.add(Это SQL выражение )
вызывает исключение в msvcrt.dll
Самое интересное что если обрамить в скобки(даже в одну скобку выражение FROM, т.е.
(
from (select convert(char(10),Traindate,2) as value
from SourceTrains group by convert(char(10),Traindate,2)
) A
where trainId=:param1
) <- эту скобку можно даже не ставить.
то исключение не генерируется.
Но само SQL выражение не корректно.
Что это за баг? и Как его обойти
Anatoly Podgoretsky (2007-11-19 15:26:00) [81]> oxffff (19.11.2007 15:12:07) [67]
Это баг, но привел к нему ты, кострукцией B := B + Text
Баг устранен в следующей версии Дельфи.
oxffff (2007-11-19 15:12:00) [82]
> sniknik © (19.11.07 14:58) [66]
Строки не хитрее нас с вами.
Что значит гарантируется?
Если передается параметр по значению.
То его значение не должно меняться.
Это правило.
>и получать выражение (если оно нужно) оттуда где оно гарантируется.
мне нужен результат и неизмененоое значение входного параметра.
А то что эта функция производят прямое взаимодействие со строкой и нарушает семантику типа. То это БАГ.
sniknik (2007-11-19 14:58:00) [83]> Запустите
я понял что ты хочеш сказать с первого раза...
но учитывая
Anatoly Podgoretsky © (19.11.07 14:35) [62]
> Строки это очень хитрая вещь
+ отсутствие var для параметра, + что строка это всетаки указатель и работа в процедуре идет с ней по адресу (value:= PChar(...)) + непонятное(бессмысленное) компилятору действие
=
> а если сделать правильно?
и получать выражение (если оно нужно) оттуда где оно гарантируется.
oxffff (2007-11-19 14:42:00) [84]
> sniknik © (19.11.07 14:27) [59]
> > А если
> а если сделать правильно?
> ...
> b:= a.Parameters.ParseSQL(b,true);
> ...
> (параметр b, не var чтобы расчитывать на возврат)
Запустите
a:=TADODataSet.Create(nil);
a.Connection:=ADOConnection;
b:=b+'select * from abc where a=:param1';
c:=a.Parameters.ParseSQL(b,true);
if pointer(b)=pointer(c) then showmessage('Idential Ref');
oxffff (2007-11-19 14:38:00) [85]
> showmessage(Dataset.Parameters.ParseSQL(SQL,true)) дает
> 0. :)
showmessage(inttostr(Dataset.Parameters.count));
oxffff (2007-11-19 14:37:00) [86]
> Anatoly Podgoretsky © (19.11.07 14:33) [61]
Во во, И я о том же. Сидел и думал почему, когда я делаю так
Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
Dataset.Parameters.ParseSQL(SQL,true);
showmessage(Dataset.Parameters.ParseSQL(SQL,true)) дает 0. :)
Пришлось поправить на
Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(DupeString(SQL,1),true);
Dataset.Parameters.ParseSQL(SQL,true);
Anatoly Podgoretsky (2007-11-19 14:35:00) [87]
> sniknik © (19.11.07 14:27) [59]
Строки это очень хитрая вещь, могут быть любые сюрпризы, тем более когда в таком странном виде.
Anatoly Podgoretsky (2007-11-19 14:33:00) [88]Проверил.
В Д7 ошибка есть, и не зависит присваивается ли результат функции переменной.
В Д10 ошибка устранена.
oxffff (2007-11-19 14:30:00) [89]
> sniknik © (19.11.07 14:27) [59]
Вы что-то не поняли.
b:=b+'select * from abc where a=:param1';
a.Parameters.ParseSQL(b,true);
showmessage(b);
на экране будет select * from abc where a=?
А не 'select * from abc where a=:param1
sniknik (2007-11-19 14:27:00) [90]> А если
а если сделать правильно?
...
b:= a.Parameters.ParseSQL(b,true);
...
(параметр b, не var чтобы расчитывать на возврат)
oxffff (2007-11-19 14:26:00) [91]
> Anatoly Podgoretsky © (19.11.07 14:23) [56]
А вы посмотрите реализацию ParseSQL.
И все станет ясно.
Я на эти грабли 2 часа убил.
Anatoly Podgoretsky (2007-11-19 14:25:00) [92]
> ты эта, невнимательно мой пост прочел.
Разве нет, если не понял, то доведи свою мысль. Мой ответ касается MS SQL и как подготавливаются запросы, если в запросе будет изменен хотя бы один символ, то он будет перекомпилирован, со статистикой 0 и неизвестным планом.
Anatoly Podgoretsky (2007-11-19 14:23:00) [93]Что то с оптимизацией и со ссылками в строках. Второй вариант работает не правильно. Что именно не пойму, но это последствие b+ и то что функция ParseSQLиспользуется как процедура.
Во втором варианте есть побочное использование b, результат почему то помещенно в нее.
Сейчас проверю на своем компиляторе.
Сусл (2007-11-19 14:20:00) [94]
> [49] Anatoly Podgoretsky © (19.11.07 13:30)
>
> WHERE DT=:DT
> при любых DT как минимум компилирование будет только один
> раз, но также сработает и статистика, в результате если
> 19 числа запрос выполнялся за 30 секунд, то 20 возможно
> уже за 10 секунд.
ты эта, невнимательно мой пост прочел.
oxffff (2007-11-19 14:16:00) [95]b:='select * from abc where a=:param1';
a.Parameters.ParseSQL(b,true);
showmessage(b);
на экране select * from abc where a=:param1
А если
b:=b+'select * from abc where a=:param1';
a.Parameters.ParseSQL(b,true);
showmessage(b);
на экране select * from abc where a=?
oxffff (2007-11-19 14:13:00) [96]
> Anatoly Podgoretsky © (19.11.07 14:09) [52]
> > oxffff (19.11.2007 14:05:51) [51]
>
> Зачем в угадайку играть?
> Но меня здесь смучает b+, зачем?
А затем чтобы счетчик был не FFFFFFFF.
Anatoly Podgoretsky (2007-11-19 14:09:00) [97]> oxffff (19.11.2007 14:05:51) [51]
Зачем в угадайку играть?
Но меня здесь смучает b+, зачем?
oxffff (2007-11-19 14:05:00) [98]
> Anatoly Podgoretsky © (19.11.07 13:34) [50]
Да я еще на одни такие грабли наткнулся. Но уже в Delphi реализации.
Грабли следующие
Запустите следующий код
var a:TADODataSet;
b:string;
begin
inherited;
a:=TADODataSet.Create(nil);
b:=b+'select * from abc where a=:param1';
a.Parameters.ParseSQL(b,true);
showmessage(b);
и посмотрите чему равно b
Anatoly Podgoretsky (2007-11-19 13:34:00) [99]> oxffff (19.11.2007 13:29:48) [48]
Не обращай ты внимание на Execute, это первый попавшийся пример. Для dataset тоже самое, только Open
Правда я эту технику использовал только на БДЕ, там эта проблема с параметрами наблюдалась, а на АДО я ни разу не наткнулся. Но я помню эту технологию на случай возникновение проблем.
Anatoly Podgoretsky (2007-11-19 13:30:00) [100]
> грусновато, Анатолий, от тебя это слышать.
Почему же грустно, это же обусловлено принципом работы сервера
Например
WHERE DT='20071119'
и
WHERE DT='20071120'
Будет проводится полный комплекс от разбора до компиляции запроса, а
WHERE DT=:DT
при любых DT как минимум компилирование будет только один раз, но также сработает и статистика, в результате если 19 числа запрос выполнялся за 30 секунд, то 20 возможно уже за 10 секунд.