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

Вниз

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

 
ЮЮ ©   (2007-11-19 12:24) [40]

> Нет именно.
>
> a.ParamCheck:=false;
> a.CommandText:=a.Parameters.ParseSQL(текст_запроса,true)
>
> a.Parameters.ParseSQL(текст_запроса,true);


Тогда третья строка, пожалуй, лишняя - ведь всё это уже выполнено во аторой.


 
ЮЮ ©   (2007-11-19 12:25) [41]

> Тогда третья строка, пожалуй, лишняя - ведь всё это уже
> выполнено во аторой.

Мда, поспешил. a.CommandText:= очистит a.Parameters


 
oxffff ©   (2007-11-19 12:26) [42]


> ЮЮ ©   (19.11.07 12:24) [40]


После второй строки  a.Parameters.Count=0.


 
Anatoly Podgoretsky ©   (2007-11-19 12:27) [43]

> oxffff  (19.11.2007 12:20:39)  [39]

Это странное слово - собака друг человека.
В данной строке должен быть запрос, а вот следующая строка как раз и занимается парсингом и созданием параметров, и то иногда не сможет исправиться. Кроме этого можно параметр создать и в ДизайнТайм, для фиксированых запросов.


 
oxffff ©   (2007-11-19 12:36) [44]


> Anatoly Podgoretsky ©   (19.11.07 12:27) [43]


Если сделать, на чем настаиваете вы, а именно

a.CommandText:=текст_запроса
a.Parameters.ParseSQL(текст_запроса,true);
..
a.open;

тогда ошибка следующая
Incorrect systax near :

при Adodataset.open


 
oxffff ©   (2007-11-19 12:40) [45]


> Кроме этого можно параметр создать и в ДизайнТайм, для фиксированых
> запросов.


В том то и дело, что запросы у меня формируются на лету.
И количество параметров меняется в зависимости от условий.
Генератор запроса сам ищет нужный параметр в классе формы и заполняет его на лету.
Таким образом я здесь вообще не принимаю участия, за исключением написания этой логики.


 
Сусл ©   (2007-11-19 12:54) [46]


>  [37] Anatoly Podgoretsky ©   (19.11.07 11:33)
> > Сусл  (19.11.2007 11:26:35)  [35]
>
> И выяснеешь у сервера, а в каком виде он например принимает
> даты.
> Про оптимизацию я вообще молчу, про нее можешь забыть.


грусновато, Анатолий, от тебя это слышать.
1. конкретный сервер всегда имеет универсальный формат даты, которые понимается всегда. есть он и у mssql.
2. ты смотрел профайлером как вызывается например AdoCommand? Это приводит к вызову sp_executesql. никто мне не запрещает пользоваться его параметрами самому. оптимизация (я так понимаю повторное использование плана запроса) в этом случае будет работать прекрасно.
а для оптимизации существенно важднее при использовании sp_executesql не забывать давать fully qualified всем таблицами и запросам (документированная, кстати, фича).


 
Anatoly Podgoretsky ©   (2007-11-19 13:13) [47]

Вот пример из одного очень древнего проекта
CommonCommand.CommandText := "DELETE FROM AuditDocuments WHERE OperationTime<:D";
CommonCommand.Parameters.ParseSQL(CommonCommand.CommandText, True);
CommonCommand.Parameters.ParamByName("D").Value := Now - 30;
CommonCommand.Execute;

ParamCheck = False


 
oxffff ©   (2007-11-19 13:29) [48]


> Anatoly Podgoretsky ©   (19.11.07 13:13) [47]


А у меня пример из сегодняшнего проекта. :)
Только у меня TadoDataset у которого нет Execute.
+запрос для возврат набора данных.


 
Anatoly Podgoretsky ©   (2007-11-19 13:30) [49]


> грусновато, Анатолий, от тебя это слышать.

Почему же грустно, это же обусловлено принципом работы сервера
Например

WHERE DT="20071119"

и

WHERE DT="20071120"

Будет проводится полный комплекс от разбора до компиляции запроса, а

WHERE DT=:DT

при любых DT как минимум компилирование будет только один раз, но также сработает и статистика, в результате если 19 числа запрос выполнялся за 30 секунд, то 20 возможно уже за 10 секунд.


 
Anatoly Podgoretsky ©   (2007-11-19 13:34) [50]

> oxffff  (19.11.2007 13:29:48)  [48]

Не обращай ты внимание на Execute, это первый попавшийся пример. Для dataset тоже самое, только Open
Правда я эту технику использовал только на БДЕ, там эта проблема с параметрами наблюдалась, а на АДО я ни разу не наткнулся. Но я помню эту технологию на случай возникновение проблем.


 
oxffff ©   (2007-11-19 14:05) [51]


> 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 14:09) [52]

> oxffff  (19.11.2007 14:05:51)  [51]

Зачем в угадайку играть?
Но меня здесь смучает b+, зачем?


 
oxffff ©   (2007-11-19 14:13) [53]


> Anatoly Podgoretsky ©   (19.11.07 14:09) [52]
> > oxffff  (19.11.2007 14:05:51)  [51]
>
> Зачем в угадайку играть?
> Но меня здесь смучает b+, зачем?


А затем чтобы счетчик был не FFFFFFFF.


 
oxffff ©   (2007-11-19 14:16) [54]

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=?


 
Сусл ©   (2007-11-19 14:20) [55]


>  [49] Anatoly Podgoretsky ©   (19.11.07 13:30)
>
> WHERE DT=:DT
> при любых DT как минимум компилирование будет только один
> раз, но также сработает и статистика, в результате если
> 19 числа запрос выполнялся за 30 секунд, то 20 возможно
> уже за 10 секунд.


ты эта, невнимательно мой пост прочел.


 
Anatoly Podgoretsky ©   (2007-11-19 14:23) [56]

Что то с оптимизацией и со ссылками в строках. Второй вариант работает не правильно. Что именно не пойму, но это последствие b+ и то что функция ParseSQLиспользуется как процедура.
Во втором варианте есть побочное использование b, результат почему то помещенно в нее.
Сейчас проверю на своем компиляторе.


 
Anatoly Podgoretsky ©   (2007-11-19 14:25) [57]


> ты эта, невнимательно мой пост прочел.

Разве нет, если не понял, то доведи свою мысль. Мой ответ касается MS SQL и как подготавливаются запросы, если в запросе будет изменен хотя бы один символ, то он будет перекомпилирован, со статистикой 0 и неизвестным планом.


 
oxffff ©   (2007-11-19 14:26) [58]


> Anatoly Podgoretsky ©   (19.11.07 14:23) [56]


А вы посмотрите реализацию ParseSQL.
И все станет ясно.
Я на эти грабли 2 часа убил.


 
sniknik ©   (2007-11-19 14:27) [59]

> А если
а если сделать правильно?
...
b:= a.Parameters.ParseSQL(b,true);
...
(параметр b, не var чтобы расчитывать на возврат)


 
oxffff ©   (2007-11-19 14:30) [60]


> 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


 
Anatoly Podgoretsky ©   (2007-11-19 14:33) [61]

Проверил.
В Д7 ошибка есть, и не зависит присваивается ли результат функции переменной.

В Д10 ошибка устранена.


 
Anatoly Podgoretsky ©   (2007-11-19 14:35) [62]


> sniknik ©   (19.11.07 14:27) [59]

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


 
oxffff ©   (2007-11-19 14:37) [63]


> 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);


 
oxffff ©   (2007-11-19 14:38) [64]


> showmessage(Dataset.Parameters.ParseSQL(SQL,true)) дает
> 0. :)


showmessage(inttostr(Dataset.Parameters.count));


 
oxffff ©   (2007-11-19 14:42) [65]


> 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");


 
sniknik ©   (2007-11-19 14:58) [66]

> Запустите
я понял что ты хочеш сказать с первого раза...

но учитывая

Anatoly Podgoretsky ©   (19.11.07 14:35) [62]
> Строки это очень хитрая вещь

+ отсутствие var для параметра, + что строка это всетаки указатель и работа в процедуре идет с ней по адресу (value:= PChar(...)) + непонятное(бессмысленное) компилятору действие

=
> а если сделать правильно?
и получать выражение (если оно нужно) оттуда где оно гарантируется.


 
oxffff ©   (2007-11-19 15:12) [67]


> sniknik ©   (19.11.07 14:58) [66]


Строки не хитрее нас с вами.
Что значит гарантируется?
Если передается параметр по значению.
То его значение не должно меняться.
Это правило.

>и получать выражение (если оно нужно) оттуда где оно гарантируется.

мне нужен результат и неизмененоое значение входного параметра.

А то что эта функция производят прямое взаимодействие со строкой и нарушает семантику типа. То это БАГ.


 
Anatoly Podgoretsky ©   (2007-11-19 15:26) [68]

> oxffff  (19.11.2007 15:12:07)  [67]

Это баг, но привел к нему ты, кострукцией B := B + Text
Баг устранен в следующей версии Дельфи.


 
oxffff ©   (2007-11-19 15:34) [69]


> Anatoly Podgoretsky ©   (19.11.07 15:26) [68]


Что значит я привел?

То есть вы хотите сказать, что это нормально?
А правильно вас понял?


 
Сусл ©   (2007-11-19 15:34) [70]


>  [57] Anatoly Podgoretsky ©   (19.11.07 14:25)
>
> > ты эта, невнимательно мой пост прочел.
>
> Разве нет, если не понял, то доведи свою мысль. Мой ответ
> касается MS SQL и как подготавливаются запросы, если в запросе
> будет изменен хотя бы один символ, то он будет перекомпилирован,
> со статистикой 0 и неизвестным планом.


запрос все равно в большинстве случаев выливается в вызов sp_executesql
так тебе никто не мешает самому пользоваться ентой штукой.
вот о чем речь.


 
oxffff ©   (2007-11-19 15:36) [71]


> Это баг, но привел к нему ты, кострукцией B := B + Text


Да какая конструкция. Эта конструкция нужна для того, чтобы выявить бажную ситуацию. И сделано для того, чтобы строка была в куче, а сегменте данных. Я же вам написал

oxffff ©   (19.11.07 14:13) [53]
oxffff ©   (19.11.07 14:30) [60]


 
oxffff ©   (2007-11-19 15:39) [72]

oxffff ©   (19.11.07 15:36) [71]

Точнее
 oxffff ©   (19.11.07 14:16) [53]
 oxffff ©   (19.11.07 14:16) [54]


 
Anatoly Podgoretsky ©   (2007-11-19 15:39) [73]

> oxffff  (19.11.2007 15:34:09)  [69]

Нет, я так не говорил, это не нормально, как ошибка, так и код.
Твое объяснение насчет ссылок меня не убедило.


 
Anatoly Podgoretsky ©   (2007-11-19 15:40) [74]

> oxffff  (19.11.2007 15:36:11)  [71]

Я возможно не понимаю истинной цели данной операции.


 
Anatoly Podgoretsky ©   (2007-11-19 15:43) [75]

> Сусл  (19.11.2007 15:34:10)  [70]

Можно много чего, но я предпочту стандартный механизм. Но если ты обеспечишь изменение запроса, что бы получилось where a=? и сумеешь передать параметры, тогда да, но тогда это ничем не будет отличаться от стандартного пути + некоторый геморой.
А как выполняются запросы в MS SQL неплохо описано в BOL, я попытался рассказать на рабоче-крестьянском. Ведь если я даже и стремлюсь переубедить тебя, то не очень настойчиво.


 
oxffff ©   (2007-11-19 16:09) [76]


> Anatoly Podgoretsky ©   (19.11.07 15:40) [74]
> > oxffff  (19.11.2007 15:36:11)  [71]
>
> Я возможно не понимаю истинной цели данной операции.


> Anatoly Podgoretsky ©   (19.11.07 15:40) [74]


Потому что для строкового литерала(который размещен в сегменте данных будет создана копия при  Result := SQL (первая строка ParseSQL)

А для не строкового литерала будет просто увеличен счетчик.

См. реализацию LStrLAsg


 
oxffff ©   (2007-11-19 16:11) [77]


> oxffff ©   (19.11.07 16:09) [76]


А далее идет прямое обращение со строкой приводя ее к pchar, тем самым нарушая семантику типа.
Отсюда грабли.

Теперь понятно??


 
Anatoly Podgoretsky ©   (2007-11-19 16:15) [78]

> oxffff  (19.11.2007 16:09:16)  [76]

Это то понятно, а вот цель нет.


 
sniknik ©   (2007-11-19 16:21) [79]

> Теперь понятно??
а вот теперь мне не понятно, получается ты специально "сбил настройки", в полном уме и трезвой памяти, а после удивляешься "ой, а тут получается разный результат", получая этот результат оттуда откуда не должен...
зачем?


 
oxffff ©   (2007-11-19 16:30) [80]

Anatoly Podgoretsky ©   (19.11.07 16:15) [78]
sniknik ©   (19.11.07 16:21) [79]

Начнем по порядку.
1. Баг1 не некорректная обработка параметров провайдером.

--> Решение

Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
Dataset.Parameters.ParseSQL(SQL,true);

Но поскольку у меня вместо SQL был вызов процедуры которая возвращает WideString. А поскольку в двух вызовах создается две копии string. Поэтому одна на другую не влияет.

Далее.

Я делаю так

SQL:=                            <- здесь это уже string
Dataset.ParamCheck:=false;
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
Dataset.Parameters.ParseSQL(SQL,true);

и нарываюсь на другие грабли уже в delphi.
По скольку если строка в куче, то параметров после вызова
Dataset.CommandText:=Dataset.Parameters.ParseSQL(SQL,true);
уже нет.
По скольку они заменены на ? напрямую во входном параметре.

А после вызов Dataset.Parameters.ParseSQL(SQL,true);

не создает параметров. По скольку в строке уже их нет.

Чего не понятно то?



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

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

Наверх




Память: 0.65 MB
Время: 0.029 c
2-1205924964
SKIPtr
2008-03-19 14:09
2008.04.13
использование TValueListEditor


4-1186816191
Игорь_1
2007-08-11 11:09
2008.04.13
Listbox


2-1205594669
DJ_UZer
2008-03-15 18:24
2008.04.13
Выделение в memo


15-1204011180
Small Donkey
2008-02-26 10:33
2008.04.13
Интернет радио


15-1203951929
Tirael
2008-02-25 18:05
2008.04.13
как получить document?