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

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

SQL выражение в ADO вызывает исключение в msvcrt.dll


Страницы:   1 2 3 4 5 6 7 8

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 секунд.


Страницы:   1 2 3 4 5 6 7 8

Наверх

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